Solved

Creating a shopify scriptTag using gql in the react and nodejs app

zahraazeem98
Tourist
11 1 2

I'm a beginner at Shopify and react js and am trying to develop an app for Shopify using node js and react js. In the index.js file, I want to create a Shopify ScriptTag and have given creating permissions to the app. So when I compile and run it, the app doesn't display any error, compiles successfully, and returns the Hello statement, but doesn't create the script. Can anyone guide me to create a script tag?

[Directory image][1]


Below is the code of Index.js which is in the pages folder
```index.js```

import {useQuery, useMutation, gql} from '@apollo/client';

const CREATE_SCRIPT_TAG = gql`
mutation scriptTagCreate($input: ScriptTagInput!){
scriptTagCreate(input: $input) {
scriptTag {
id
}
userErrors {
field
message
}
}
}
`;
function Index() {
// console.log('Hello hello')
// useMutation(CREATE_SCRIPT_TAG, {variables: {input: {src: "https://eb7645e45ebf.ngrok.io/script-tag.js", displayScope: "ALL",
// event: "onload"}}});
useMutation({variables: {input: {src: "https://f2c8353e41aa.ngrok.io/script-tag.js", displayScope: "ALL"}} });

return(<div><p>Sample app Next.js and hello</p></div>);
}
export default Index;

 

Below is the code of script-tag.js file which is in the public folder.
```script-tag.js```

console.log('this is me script tag!!!!!!!!')
const header = $('header.site-header').parent();

header.prepend('<div>Hello this is coming from the public folder </div>').css({'background-color':'orange', 'text-align': 'center'})


Code for _app.js

import App from 'next/app';
import Head from 'next/head';
import React from 'react';
import Cookies from 'js-cookie';
import {Provider} from '@shopify/app-bridge-react';
import { AppProvider } from '@shopify/polaris';
import '@shopify/polaris/dist/styles.css';
import translations from '@shopify/polaris/locales/en.json';
import { ApolloClient, InMemoryCache } from '@apollo/client';
import { ApolloProvider } from '@apollo/client';

const client = new ApolloClient({
fetchOptions: {
credentials: 'include',
},
cache: new InMemoryCache()
});

class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
const config = { apiKey: API_KEY, shopOrigin: Cookies.get('shopOrigin'), forceRedirect: true };
return (
<React.Fragment>
<Head>
<title>Sample App</title>
<meta charSet="utf-8" />
</Head>
<Provider config={config}>
<AppProvider i18n={translations}>
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
</AppProvider>
</Provider>
</React.Fragment>
);
}
}

export default MyApp;


Server.js

require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');
const { verifyRequest } = require('@shopify/koa-shopify-auth');
const session = require('koa-session');

dotenv.config();
const {default: graphQLProxy} = require('@shopify/koa-shopify-graphql-proxy');
const {ApiVersion} = require('@shopify/koa-shopify-graphql-proxy');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;

app.prepare().then(() => {
const server = new Koa();
server.use(session({ secure: true, sameSite: 'none' }, server));
server.keys = [SHOPIFY_API_SECRET_KEY];

server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
scopes: ['read_products', 'write_products', 'write_script_tags', 'read_script_tags'],
afterAuth(ctx) {
const { shop, accessToken } = ctx.session;
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none'
})
ctx.redirect('/');
},
}),
);

server.use(graphQLProxy({version: ApiVersion.October20}));
server.use(verifyRequest());
server.use(async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
return
});

server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
Accepted Solutions (2)

Mircea_Piturca
Shopify Partner
1547 44 345

This is an accepted solution.

Your ScriptTag API can be called in server.js, in the afterAuth function. This function is called after your app is installed and authenticated.

I am not sure about your mutation. You can look at this appSubscriptionCreate mutation and modify it for your use case: https://github.com/Shopify/shopify-demo-app-node-react/blob/master/server/getSubscriptionUrl.js

Finally—Add variant descriptions to your products

View solution in original post

zahraazeem98
Tourist
11 1 2

This is an accepted solution.

 I just removed the `` in the JSON.stringify function and it worked.  Thanks, @Mircea_Piturca for the help.

Working function:

body: JSON.stringify({"script_tag": {
      "event": "onload"
      ,"display_scope": "all"
    }})

View solution in original post

Replies 7 (7)

Mircea_Piturca
Shopify Partner
1547 44 345

This is an accepted solution.

Your ScriptTag API can be called in server.js, in the afterAuth function. This function is called after your app is installed and authenticated.

I am not sure about your mutation. You can look at this appSubscriptionCreate mutation and modify it for your use case: https://github.com/Shopify/shopify-demo-app-node-react/blob/master/server/getSubscriptionUrl.js

Finally—Add variant descriptions to your products
zahraazeem98
Tourist
11 1 2

Hi @Mircea_Piturca! Thanks for your reply. I have checked my mutation on the GraphQl app and it works there. So, it most probably is the correct mutation query to create a Shopify script tag. 

Moreover, I have looked at the link you provided and have modified it for my app and am calling the API in the server.js now. However, it still is not working. Can you please check if I am doing something wrong. Thanks in advance.

require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');
const { verifyRequest } = require('@shopify/koa-shopify-auth');
const session = require('koa-session');

//const Cryptr = require('cryptr');


dotenv.config();
const {default: graphQLProxy} = require('@shopify/koa-shopify-graphql-proxy');
const {ApiVersion} = require('@shopify/koa-shopify-graphql-proxy');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;

app.prepare().then(() => {
  const server = new Koa();
  server.use(session({ secure: true, sameSite: 'none' }, server));
  server.keys = [SHOPIFY_API_SECRET_KEY];
  server.use(graphQLProxy({version: ApiVersion.October20}));
  server.use(
    createShopifyAuth({
      apiKey: SHOPIFY_API_KEY,
      secret: SHOPIFY_API_SECRET_KEY,
      scopes: ['read_products', 'write_products', 'write_script_tags', 'read_script_tags'],
      afterAuth(ctx) {
        const { shop, accessToken } = ctx.session;
  //      console.log(shop);
//        console.log(accessToken);
        ctx.cookies.set('shopOrigin', shop, {
          httpOnly: false,
          secure: true,
          sameSite: 'none'
      }) 
      const query = JSON.stringify(
        {
          query: `mutation {
              scriptTagCreate(input: {
                src: "https://e20eb9f4365a.ngrok.io/script-tag.js"
                displayScope: "All"
              }) {
                  scriptTag {
                      id
                  }
                  userErrors {
                      field
                      message
                  }
                }
            }`
        }
      )
  fetch(`https://${shop}/admin/api/2021-01/script_tags.json`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
  //    "X-Shopify-Access-Token": accessToken,
    },
    body: query
  }).then(async response => {
    const data = await response.json();
    // check for error response
    try{
      if (response.ok) {
        // get error message from body or default to response status
    //    const error = (data && data.message) || response.status;
     //   return Promise.reject(error);
     console.log(`no errorr!!!`);
    }
    }
    catch(error){
      this.setState({ errorMessage: error.toString() }).bind(this);
    console.error('There was an error!', error);
    }
    
});
//  const confirmationUrl = responseJson.data.scriptTagCreate.scriptTag;
   console.log(`hi`);

        ctx.redirect('/');
      },
    }),
  );

 
  server.use(verifyRequest());
  server.use(async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
    return
  });

  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`);
  });
});

/*JSON.stringify(`script_tag: {
  event: "onload",
  src: "https://e20eb9f4365a.ngrok.io/script-tag.js" 
}`) */

 

zahraazeem98
Tourist
11 1 2

This is an accepted solution.

 I just removed the `` in the JSON.stringify function and it worked.  Thanks, @Mircea_Piturca for the help.

Working function:

body: JSON.stringify({"script_tag": {
      "event": "onload"
      ,"display_scope": "all"
    }})
Mircea_Piturca
Shopify Partner
1547 44 345

@zahraazeem98 Happy, you figure it out.

Extra tip, use cache: true. This will make your ScriptTag to be loaded from Shopify's CDNs. 

Look into the docs for more info

 

Finally—Add variant descriptions to your products
zahraazeem98
Tourist
11 1 2

Okay, I will. Thanks @Mircea_Piturca .

navakiran
Visitor
1 0 0

I have one quick question here. Suppose if I need to create the script-tag only once after the app installation complete. How can I do that? Is there any event available for that?

zahraazeem98
Tourist
11 1 2

The code above does the same. it authenticates the app and creates a script tag after the installation is completed.