where to add script_tag code

Highlighted
New Member
14 0 0

we have developed one sample app and it is working and asking for all required permission whatever we are adding in scope and able to install and once installed it shows message from index.js file but we want to use script_tag to add javascript code in head section.

 

where to put this code in pages/index.js or server.js so that once app is installed required javascript is added in head

 

// test starts here
i tried this index.js but it gives internal server error and nothing is being added. 
 
request.post(accessTokenRequestUrl, { json: accessTokenPayload })
    .then((accessTokenResponse) => {
      const accessToken = accessTokenResponse.access_token;
      // DONE: Use access token to make API call to 'script_tags' endpoint
      const createScriptTagUrl = 'https://' + shop + '/admin/script_tags.json';
      const shopRequestHeaders = {
        'X-Shopify-Access-Token': accessToken,
      };
      const scriptTagBody = {
        "event": "onload",
        "src": "https:\/\/rubiconproject.com\/prebid\/11990_v2.js"
      };
 
      request.post(shopRequestUrl, { json: scriptTagBody }, { headers: shopRequestHeaders })
      .then((shopResponse) => {
        res.status(200).end(shopResponse);
      })
      .catch((error) => {
        res.status(error.statusCode).send(error.error.error_description);
      });
    })
    .catch((error) => {
      res.status(error.statusCode).send(error.error.error_description);
    });
 
// test ends here
 

  

0 Likes
Shopify Staff
Shopify Staff
1555 81 284

Is the error occurring on Shopify's end or yours? I can't speak for the latter, but if it's a Shopify error you could capture an X-Request-Id response header from the Shopify response and I can check logs. One thing you might want to consider, and this is just a guess, is structuring your payload a little bit differently by nesting your script tag properties inside of a script tag parent object:

 

      const scriptTagBody = {
        "script_tag": {
          "event": "onload",
          "src": "https:\/\/rubiconproject.com\/prebid\/11990_v2.js"
        }
      };

Cheers.

0 Likes
Highlighted
Excursionist
10 1 0

Hello,

 

See the below code for adding/getting/deleting the script_tags. I have written this in typescript for my app. I'm calling this on my callback event when my app loads inside the iframe of Shopify admin. When the page loads it authorize the app and return the app on callback redirect Url which contains a shop, hmac, code and state; from there I'm passing the code property to generate the access token. 

 

Use index.js. See my ts code what I'm doing

 

public ConfigureAuthenticatorCallback(): void {
        this.app.get("/callback", (req: any, res: any) => {
            let { shop, hmac, code, state } = req.query;
            let stateCookie = cookie.parse(req.headers.cookie).state;

            if (state !== stateCookie) {
                return res.status(400).send("Request origin cannot be verified");
            }

            if (shop && hmac && code) {
                const map = Object.assign({}, req.query);
                delete map['hmac'];
                const message = queryString.stringify(map);
                const generateHash = crypto.createHmac('sha256', settings.API_SECRET).update(message).digest('hex');

                if (generateHash !== hmac) {
                    return res.status(400).send("HMAC validation fialed");
                }

                // check if tags are in place.
                this.AddScriptTags(code);

                // render my index.html in iframe
                res.render('index');

            } else {
                res.status(400).send("Required parameters missing");
            }
        });
    }

See how I'm checking the tags and adding them.

    public async AddScriptTags(code: string, deleteAll: boolean = false): Promise<void> {

        let accessTokenObj = this.memoryCache.get("access_token") as any;

        // if key is expired or not exists
        if (accessTokenObj == undefined) {
            // generate access token first
            let post = bent(`https://${settings.SHOP_URL}/admin/oauth/access_token`, 'POST', 'json', 200);
            let response = await post('', {
                client_id: settings.API_KEY,
                client_secret: settings.API_SECRET,
                code
            }) as any;

            this.memoryCache.set("access_token", response);
            accessTokenObj = response;
        }

        // check in-memory if tag is already added
        let script_tags_obj = this.memoryCache.get("script_tags") as {
            script_tags: Array<{
                created_at: ""
                display_scope: ""
                event: ""
                id: 0
                src: ""
                updated_at: ""
            }>
        };

        if (script_tags_obj == undefined) {
            // get tags from server if key doesn't exists
            if (accessTokenObj != null && accessTokenObj.access_token != undefined) {
                let get = bent(`https://${settings.SHOP_URL}/admin/api/2020-01/script_tags.json`, 'GET', 'json', 200);
                let response = await get('', '', {
                    'X-Shopify-Access-Token': accessTokenObj.access_token
                }) as any

                if (deleteAll) {
                    // delete all (optional) in-case if i want to delete all tags manually.
                    // as they will automatically removed when I'll uninstall the app from shopify
                    if (response != null && response.script_tags.length > 0) {
                        for (let script of response.script_tags) {
                            await this.DeleteAllScriptTags(script.id, accessTokenObj.access_token);
                        }
                    }

                    return;
                }

                // set to memory cache so we don't need to fetch everytime
                // also saving script tags id for future actions.
                if (response != null && response.script_tags.length > 0) {
                    this.memoryCache.set("script_tags", response);
                    script_tags_obj = response;
                }

                console.log(response);
            }
        }

        // before adding tag make sure it should not exists by url
        if (script_tags_obj != undefined && script_tags_obj.script_tags.length > 0) {
            let script_tag = script_tags_obj.script_tags.find(n => n.src=== settings.FRONTEND_SCRIPT_URL);
            if (script_tag == undefined) {
                this.AddScriptTag(settings.FRONTEND_SCRIPT_URL, "onload", accessTokenObj.access_token);
            }
        } else if (script_tags_obj == undefined) { // if there is no tags + no key in-memory then add
            this.AddScriptTag(settings.FRONTEND_SCRIPT_URL, "onload", accessTokenObj.access_token);
        }
    }
    public async DeleteAllScriptTags(id: string, access_token: string): Promise<void> {
        let del = bent(`https://${settings.SHOP_URL}/admin/api/2020-01/script_tags/${id}.json`, 'DELETE', 'json', 200);
        let response = await del('', '', {
            'X-Shopify-Access-Token': access_token
        });
        console.log(response);
    }

    public async AddScriptTag(scriptUrl: string, event: string, access_token: string): Promise<void> {
        let post = bent(`https://${settings.SHOP_URL}/admin/api/2020-01/script_tags.json`, 'POST', 'json', 201);
        let response = await post('', {
            "script_tag": {
                "event": event,
                "src": scriptUrl
            }
        }, {
            'X-Shopify-Access-Token': access_token
        });
        console.log(response);
    }

I hope this helps someone!

 

0 Likes