Shopify Script tags conditional dispatching

Shopify 2.0 themes now offer the use of app blocks. If a theme is using app blocks, then your app shouldn't dispatch any script tags. Now if you're an laravel app developer you're probably using this laravel package from osiset.

Unfortunately this package does not yet provide the possibility to ask if app blocks are available or not. If you're using the package then script tags will always be dispatched. If you want need to load the script tags conditional, then you will have to do a little editing.

All of the code that I will show you here will work with the package at version 17.1. So you should make sure to upgrade your laravel package.

all credits of this code go to https://github.com/apurbajnu as he coded it you can also read along this GitHub Issue: https://github.com/osiset/laravel-shopify/issues/980#issuecomment-991649153. I just made some slide changes to make the code work with version 17.1

Also make sure to give your app the correct access scopes. In order to check for app blocks, you need to give your app the 'read_themes' scope!

  1. Go to the env file and add this line depending on whatever template you need.

2. Go to config/shopify-app.php and add this line.

3. Go to vendor/osiset/laravel-shopify/src/Contracts/ApiHelper.php and add these lines.

4. Go to vendor/osiset/laravel-shopify/src/Services/ApiHelper.php and add these lines. (carbon.now.sh won't let me copy such long lines of code, that's why this code looks a little ugly)

    public function getThemes(array $params = []): ResponseAccess
    {
        // Setup the params
        $reqParams = array_merge(
            [
                'limit' => 250,
                'fields' => 'id,role',
            ],
            $params
        );

        // Fire the request
        $response = $this->doRequest(
            ApiMethod::GET(),
            '/admin/themes.json',
            $reqParams
        );

        return $response['body']['themes'];
    }

    /**
     * {@inheritdoc}
     */


    public function getThemes(array $params = []): ResponseAccess
    {
        // Setup the params
        $reqParams = array_merge(
            [
                'limit' => 250,
                'fields' => 'id,role',
            ],
            $params
        );

        // Fire the request
        $response = $this->doRequest(
            ApiMethod::GET(),
            '/admin/themes.json',
            $reqParams
        );

        return $response['body']['themes'];
    }

    /**
     * {@inheritdoc}
     */


    public function scriptTagShouldBeEnabled(array $app_block_templates = [], array $params = []): bool
    {

        if (count($app_block_templates) > 0) {

            $themes = $this->getThemes();
            $published_theme = null;
            $templateJSONFiles = [];
            $sectionsWithAppBlock = [];
            $main = false;
            $templateMainSections = [];
            if (count($themes) !== 0) {
                foreach ($themes as $theme) {
                    if ($theme['role'] === 'main') {
                        $published_theme = $theme['id'];
                    }
                }
            }

            if (!is_null($published_theme)) {
                // Setup the params
                $reqParams = array_merge(
                    [
                        'fields' => 'key',
                    ],
                    $params
                );

                // Fire the request
                $response = $this->doRequest(
                    ApiMethod::GET(),
                    "/admin/themes/{$published_theme}/assets.json",
                    $reqParams
                );


                $assets = $response['body']['assets'];

                if (count($assets) > 0) {
                    foreach ($assets as $asset) {

                        foreach ($app_block_templates as $template) {

                            $trimmedTemplate = trim($template);

                            if ($asset['key'] === "templates/{$trimmedTemplate}.json") {

                                $templateJSONFiles[] = $asset['key'];
                            }
                        }
                    }

                    if (count($templateJSONFiles) == count($app_block_templates)) {
                        foreach ($templateJSONFiles as $file) {
                            $acceptsAppBlock = false;
                            $reqParams = array_merge(
                                [
                                    'fields' => 'value',
                                ],
                                ['asset[key]' => $file]
                            );

                            // Fire the request
                            $response = $this->doRequest(
                                ApiMethod::GET(),
                                "/admin/themes/{$published_theme}/assets.json",
                                $reqParams
                            );

                            $asset = $response['body']['asset'];

                            $json = json_decode($asset['value'], true);
                            $query = 'main-';

                            if (array_key_exists('sections', (array)$json) && count($json['sections']) > 0) {
                                foreach ($json['sections'] as $key => $value) {
                                    if ($key === 'main' || substr($value['type'], 0, strlen($query)) === $query) {
                                        $main = $value;
                                        break;
                                    }
                                }
                            }

                            if ($main) {
                                $mainType = $main['type'];
                                if (count($assets) > 0) {
                                    foreach ($assets as $asset) {
                                        if ($asset['key'] === "sections/{$mainType}.liquid") {
                                            $templateMainSections[] = $asset['key'];
                                        }
                                    }
                                }
                            }
                        }

                        if (count($templateMainSections) > 0) {
                            $templateMainSections = array_unique($templateMainSections);
                            foreach ($templateMainSections as $templateSection) {
                                $acceptsAppBlock = false;
                                $reqParams = array_merge(
                                    [
                                        'fields' => 'value',
                                    ],
                                    ['asset[key]' => $templateSection]
                                );

                                // Fire the request
                                $response = $this->doRequest(
                                    ApiMethod::GET(),
                                    "/admin/themes/{$published_theme}/assets.json",
                                    $reqParams
                                );
                                $asset = $response['body']['asset'];

                                $match = preg_match('/\{\%\s+schema\s+\%\}([\s\S]*?)\{\%\s+endschema\s+\%\}/m', $asset['value'], $matches);

                                $schema = json_decode($matches[1], true);

                                if ($schema && array_key_exists('blocks', $schema)) {
                                    foreach ($schema['blocks'] as $block) {
                                        if (array_key_exists('type', (array)$block) && $block['type'] === '@app') {
                                            $acceptsAppBlock = true;
                                        }
                                    }
                                    //   $acceptsAppBlock = .some((b => b.type === '@app'));
                                }
                                $acceptsAppBlock ? array_push($sectionsWithAppBlock, $templateSection) : null;
                            }
                        }
                    }



                    if (count($sectionsWithAppBlock) > 0  && count($sectionsWithAppBlock) === count($templateJSONFiles)) {
                        return false;
                    }

                    if (count($sectionsWithAppBlock) > 0) {
                        return false;
                    }
                }
            }
        }

        return true;
    }

6. Go To vendor/osiset/laravel-shopify/src/Actions/DispatchScripts.php and add these lines

so the __invoke Method at DispatchScripts.php should look something like this:

Now you need just need to make sure to override those classes in your project. Otherwise all your code will be overriden the next you update the package!

I hope this could help you a little bit when you build your shopify app!