How To Show/send HTML To Shopify Admin?

- 1 answer

I am having an issue figuring out how to display html in the admin for an app.

I have followed the 'Build a Shopify app with Node and Express' tutorial, and am able to display json of the shop in the Shopify App Admin. However, I am not understanding the next steps of getting any html to display in the app admin. I have tried replacing the end(shopResponse) with a render method, which throws the error 'request origin cannot be verified'. I have also tried to set up an additional request, but that caused a similar error.

app.get('/shopify', (req, res) => {
  const shop =;
  if (shop) {
    const state = nonce();
    const redirectUri = forwardingAddress + '/shopify/callback';
    const installUrl = 'https://' + shop +
      '/admin/oauth/authorize?client_id=' + apiKey +
      '&scope=' + scopes +
      '&state=' + state +
      '&redirect_uri=' + redirectUri;

    res.cookie('state', state);
  } else {
    return res.status(400).send('Missing shop parameter. Please add ? to your request');

app.get('/shopify/callback', (req, res) => {
  const { shop, hmac, code, state } = req.query;
  var stateCookie = '';

  if (req.headers.cookie) {
    stateCookie = cookie.parse(req.headers.cookie).state; 

  if (state !== stateCookie) {
    return res.status(403).send('Request origin cannot be verified');

  if (shop && hmac && code) {
    const map = Object.assign({}, req.query);
    delete map['signature'];
    delete map['hmac'];
    const message = querystring.stringify(map);
    const providedHmac = Buffer.from(hmac, 'utf-8');
    const generatedHash = Buffer.from(
        .createHmac('sha256', apiSecret)
    let hashEquals = false;
    // timingSafeEqual will prevent any timing attacks. Arguments must be buffers
    try {
      hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
    // timingSafeEqual will return an error if the input buffers are not the same length.
    } catch (e) {
      hashEquals = false;

    if (!hashEquals) {
      return res.status(400).send('HMAC validation failed');

    const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
    const accessTokenPayload = {
      client_id: apiKey,
      client_secret: apiSecret,
    };, { json: accessTokenPayload })
    .then((accessTokenResponse) => {
      const accessToken = accessTokenResponse.access_token;
      // DONE: Use access token to make API call to 'shop' endpoint
      const shopRequestUrl = 'https://' + shop + '/admin/api/2019-04/themes.json';
      const shopRequestHeaders = {
        'X-Shopify-Access-Token': accessToken,

      request.get(shopRequestUrl, { headers: shopRequestH-Token': accessToken,

      request.get(shopRequestUrl, { headers: shopRequestHeaders })
      .then((shopResponse) => {
        // This is what I have tried replacing with a render method
      .catch((error) => {

    .catch((error) => {

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

I am expecting to be able to see basic html in the Shopify app admin.


After reading accepted answer, I realized I didn't need all the auth from the getting started to show the file.

My whitelisted route ended up looking like this:

app.get('/shopify/callback', (req, res) => {



Once you getting shop json succesfully it means app installed in shopify store successfully

To Display html in app for store admin you have to create one route in your project which render you to html page like as below

app.get('/', function (req, res, next) {
    res.render('your html page path');

this can render you to html page where you can display html for your app home page

Now you have to set your domain url in your shopify partner account app setup Shopify partner account click this url and go to your app >> app setup and add your https domain for your app

this root location load when your app open from shopify admin and it display you index html page for your app