DEV Community

Cover image for Using Deep Links Effectively in Your Shopify App Theme Extensions
Josh Boddy
Josh Boddy

Posted on

Using Deep Links Effectively in Your Shopify App Theme Extensions

Theme extensions are a fantastic way to let store customers engage with your app. They enable the use of App Blocks to seamlessly integrate your custom Liquid, HTML, JavaScript, and CSS code onto Shopify 2.0 storefronts, empowering customers to enjoy your app's features on most store pages (checkout pages being the exception). As an app developer, it's wise to leverage Deep Links to simplify the embedding of app blocks for your users. However, these links can seem a tad complex at first. Our goal today is to demystify Deep Links, making them more approachable and manageable for you.

Deep Link Structure

You can find the basic structure for Deep Links in Shopify's Developer Documentation, but let's break it down further, focusing on key areas:

https://<myshopifyDomain>/admin/themes/current/editor?template=${template}&addAppBlockId={uuid}/{handle}&target=newAppsSection

Enter fullscreen mode Exit fullscreen mode

This is the standard format for a Deep Link. Let's dissect it, shall we?

  • <myshopifyDomain>: This is your .myshopify.com URL, not to be confused with your shop domain. Using a custom URL here might lead to errors.
  • {template}: Refers to a page template in your Theme Editor. You can add an App Block to any page with a JSON template in your code. The product page is a prime example.
  • {uuid}: This represents the SHOPIFY_EXTENSION_NAME_ID environment variable from your project's .env file. We'll delve into how to fetch and utilise these variables in your codebase shortly.
  • {handle}: The name of your app block's liquid file. Simply omit the .liquid extension when using it here.
  • {header|footer|aside} optional: This specifies the section group for your app block. You can choose from the options provided or leave this out entirely.
  • {sectionID}: The ID of the section where you want to place your app block. You'll find this in the theme's JSON templates, listed under sections.

Now that we've got the basics down, let's explore some clever ways to streamline this process and save you some hassle.

What's the Fuss?

Knowing what a Deep Link should look like is one thing, but actually using one in your app dashboard is another kettle of fish. Where do these environment variables come from? And what on earth is a Section ID, and how do you find it?

Many of these values are dynamic, varying between stores and installations. This presents a challenge for us developers, as we need to relay data from the backend to the frontend securely (keeping environment variables off the frontend), ensuring all values are accurate and functional. Here are a few strategies to tackle this...

The Solution

Our backend can serve as a powerhouse, providing an endpoint for the frontend to query and fetch the desired app block details. Let's start with the basics of string concatenation. Store the original template URL in a constant:

const deepLinkUrl = "https://<myshopifyDomain>/admin/themes/current/editor?template=${template}&addAppBlockId={uuid}/{handle}&target=newAppsSection";

Enter fullscreen mode Exit fullscreen mode

Now, fill in the blanks with known values. For instance, if we're adding our app block to the product page, we'd set the template as product:

const deepLinkUrl = "https://<myshopifyDomain>/admin/themes/current/editor?template=product&addAppBlockId={uuid}/{handle}&target=newAppsSection";

Enter fullscreen mode Exit fullscreen mode

Next, wrap this in an endpoint to glean details from the current user session:

app.get("/api/deeplinks", (req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  const deepLinkUrl = "https://<myshopifyDomain>/admin/themes/current/editor?template=product&addAppBlockId={uuid}/{handle}&target=newAppsSection";

  res.status(200).send(deepLinkUrl);
});

Enter fullscreen mode Exit fullscreen mode

With access to the user's session info (like the current shop), we can use JavaScript's ${value} syntax for concatenation:

app.get("/api/deeplinks", (req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  const deepLinkUrl = `https://${res.locals.shopify.session.shop}/admin/themes/current/editor?template=product&addAppBlockId={uuid}/{handle}&target=newAppsSection`;

  res.status(200).send(deepLinkUrl);
});

Enter fullscreen mode Exit fullscreen mode

Adding ${res.locals.shopify.session.shop} to the URL dynamically fills in the shop's URL making the request.

Next, introduce the dotenv package to your Shopify app with npm install dotenv --save. Import it at the top of your file:

import "dotenv/config";

Enter fullscreen mode Exit fullscreen mode

This allows us to access those crucial environment variables with process.env.VARIABLE_NAME, adhering to the best practice of uppercase variable names:

import "dotenv/config";

app.get("/api/deeplinks", (req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  const deepLinkUrl = `https://${res.locals.shopify.session.shop}/admin/themes/current/editor?template=product&addAppBlockId=${process.env.SHOPIFY_EXT_NAME_ID}/{handle}&target=newAppsSection`;

  res.status(200).send(deepLinkUrl);
});

Enter fullscreen mode Exit fullscreen mode

After deploying your app (using npm run deploy), update the environment variable name in your code to match the one in your newly created .env file.

Finally, replace the {handle} placeholder with your .liquid file's name to complete your Deep Link:

import "dotenv/config";

app.get("/api/deeplinks", (req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  const deepLinkUrl = `https://${res.locals.shopify.session.shop}/admin/themes/current/editor?template=product&addAppBlockId=${process.env.SHOPIFY_EXT_NAME_ID}/APP_BLOCK_LIQUID_FILE_NAME&target=newAppsSection`;

  res.status(200).send(deepLinkUrl);
});

Enter fullscreen mode Exit fullscreen mode

Voilà! You've crafted a straightforward endpoint to fetch your Deep Link from the backend, fully populated with all necessary data. But how do you put this to use?

Simple.

In your frontend, make a request to your backend to retrieve this data, perhaps using fetch in a React template or a loader function in Remix. Then, embed this URL in a Button component. Clicking this button will effortlessly embed your app block onto a store, bypassing the need for intricate configurations or data manipulation.

Going Further

Feeling adventurous? Here's a bonus challenge: Create a list of deep link URLs for each app block you develop.

Consider using Node's fs library to scan your blocks folder within the theme app extension directory. Generate a new URL for each file, returning a list in a JSON response to the frontend. Use the .map function to craft a button for each URL, allowing you to add all your app blocks to the UI as you create them, rather than manually crafting a new button and request for each new block. But that's a story for another day. Let me know how you fare and don't hesitate to reach out with questions.

Happy coding!

- Josh

Top comments (0)