Using Deep Links Effectively in Your Shopify App Theme Extensions
Tags: shopify, webdev, javascript, tutorial
Published: 2024-02-21 14:00:00

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](https://shopify.dev/docs/apps/online-store/theme-app-extensions/extensions-framework#deep-linking), but let's break it down further, focusing on key areas:

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

```

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";

```

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";

```

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);
});

```

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);
});

```

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";

```

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);
});

```

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);
});

```

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