This is a complimentary blog post to a video from the ShopifyDevs YouTube channel. In this article, Shayne Parmelee, a Developer Advocate at Shopify, will show you how to perform one of the most common tasks of Shopify developers—adding code from an app to a client’s theme when your app interacts with or adds functionality to the theme. He'll explore the two different options that are possible and highlight the benefits of both approaches.
Shayne will walk you through how to:
- Render background JavaScript on pages
- Conditionally render a snippet using the
content_for_header
Liquid object - Automatically remove code with
ScriptTags
Build for the world’s entrepreneurs
Want to see more content just like this? Subscribe to the ShopifyDevs YouTube channel. Get development inspiration, useful tips, and practical takeaways.
SubscribeGetting started
I'm here today to talk about one of the most commonly asked questions about the developer platform: how to get code from an app into a theme efficiently and easily.
There's many different ways that people are doing this right now. I'm going to talk about two of the most common ways and which one I think is better.
Option number one is to load our code with JavaScript. This is great for background things. It works well for something line conversion tracking. However, it’s Generally not great if you have to render content that people have to view or interact with.
The second option—spoiler alert, this is the one we're going to be going with—is to conditionally render liquid content, based on the presence of a ScriptTag
. This is great for displaying things and prevents your clients from having to remove code from their themes after the app is uninstalled because it just won't render.
ScriptTags
are remote scripts that are automatically removed when an app is uninstalled and they are really important for both of these approaches. The ScriptTag
resource represents remote JavaScript code that is loaded into the pages of a shop storefront or the order status page of checkout. This lets you add functionality to those pages without modifying theme templates.
Let’s discuss the two options.
You might also like: The Shopify App CLI Tool: Build Apps Faster.
Option one: loading code with JavaScript
On the right is an example of the Debut theme, the default theme that your users are going to have when they first open their stores. There’s nothing in the Debut theme that’s been edited yet. If I make a request to see if there are any ScriptTags
, scoped to this app on this store, there aren't any, so we’ll create one.
Creating a ScriptTag
Our ScriptTag
has two different things that we need to define when we're creating it.
The first is the event. In this case, we're using the onload event. This is so we can have it load on every single page. The source is scripttags.ngrok.io
and you can read more about this in our docs. This is just a server that I've quickly set up in order to serve a ScriptTag
. Where before, this returned an empty array. Now if I make another request, the ScriptTag
has been created.
This isn't going to do a whole lot by itself, it is just an address. This needs to actually pull some JavaScript to execute on the theme. If we go to the dummy server that we've set up in Visual Studio Code, all it's doing is returning a single file, scripttag.js
. Returning to our theme, we can see that this code is appropriately rendering.
Now, this is just a little console.log
, nothing is rendering yet, so we’ll take care of that next. I'm going to paste some code that I have written before. It’s very simple, with some inline styles, a box, that's just going to say this is a bar loaded with JS, and we're going to render that in the script.div
, which we haven't written yet.
To create our script.div
, we’re going to go into our theme, edit code, and since we want this to be rendered on all pages, we're going to add it to our theme.liquid
layout. So right under the header section we're just going to say <div id=”ScriptApp”></div>
.
You might also like: How to Get Reviews for Your Shopify Apps.
A note on the expected behavior of a ScriptTag
After saving that, we can see that the bar is loading in, but there's a little bit of a problem: after the rest of the page has already loaded, it’s popping in. This is an expected behavior of ScriptTags
. This behavior is OK if we're doing something like conversion tracking, where the user doesn't actually need to actively interact with what's being rendered because it's just background JavaScript. That’s really what ScriptTags
are meant for, but it looks kind of weird for this to be loaded in after the fact.
Some app developers have done some workarounds where they'll already render this green bar with some space and then add the text later, or have placeholder text or only fill in the parts that you need a remote call for after the remote call's been made. Any way you slice it, this is code that's running after the rest of the theme has already been rendered, so something's going to pop in at some point.
Option two: conditionally rendering content with Liquid
The first thing that we're going to do for option number two is to add a new snippet. We'll call it script-tag-app
, and this is just a little piece of code that we're going to be able to reference from our other theme file. Again, it’s just a little in-line styled bar that's going to render on the theme.
Now, the {{ content_for_header }}
tag is very important. In this {{ content_for_header }}
tag will be render the addresses for all of the ScriptTags
for the page, so we can use that behavior in order to know whether or not the app is installed, as long as we always add a ScriptTag
to the shop when the app is installed. In this case, our ScriptTag
that we have created, is still here, and this is our address.
We’re going to check for the presence of this ScriptTag
in our {{ content_for_header }}
and then conditionally render that snippet that we added. Let's just say:
{% section ‘header’ %}
{% if content_for_header contains ‘script-tags.ngrok.io’ %}
{%render ‘script-tag-app’ %}
{% endif %}
Now, if I reload the page, this is always going to be here because this is being rendered by the theme rendering engine by Liquid, rather than being rendered by a remote JavaScript call.
The advantages of rendering through Liquid
We can also see that we're able to pull in contextual information about which page we're currently on. There's a huge amount of data that's available just through Liquid on the theme, and all of that is available through the Liquid renderer. This includes metadata that you can add to products, to the shop, or anything that you like. That metadata can also be pushed in by your themes in order for lightning-fast rendering times.
The benefit to this now is that if we delete the ScriptTag
and we refresh the page, our code has now disappeared. This has a very minimal impact on the performance of our theme because this just evaluates to false and this will never render. This avoids a situation where maybe if this piece here directly is just pasted in.
Let’s take away the conditional. In that case, if the app is uninstalled, there may still be the bar here that renders, even though the user may not be able to configure the bar anymore with your app.
Now, we don't want the user to have to always go into the theme editor in order to add their code every time your app is installed. We’re going to look at how to do that programmatically. If we take out all of the code that we added, we can see that nothing renders. We also have no ScriptTags
on the store, so this is pretty much back in the state that it started at.
You might also like: How to Make Your Embedded Apps Load Quickly and Reliably.
The API equivalent for viewing or editing themes
The API equivalent action of looking at which themes are currently on the store is this request here, which is a request to themes.json
. We can see that Debut is the only theme that's currently available, just like what's being shown in the admin. The API equivalent action for going and editing, or looking at a specific asset in a theme is this one here. So, we take the ID from the theme, we add /assets.json
, and then as a query, as query parameters, we add asset[key]
, and then what specific asset it is that we're looking to fetch.
In order to push the code back into our theme, we're going to make a PUT
request with what we want the content to be. In this case, where we added the code was underneath this section header part of the theme. If I now search for the section header, and I input this pre-prepared little bit of code back in, then I'm going to send this PUT
request. We're going to update the theme.liquid
file, and if I refresh, we can see what it looks like in the editor. Perfect!
Now, obviously, this isn't going to render anything yet because we don't have our ScriptTag
, but if we recreate our ScriptTag
, this is now once again showing on the store.
The same goes for our snippets: we didn't get rid of the snippet that we had made before, our ScriptTag
app snippet. But if I delete this, we can see now this is going to create an error. It couldn't find the snippet, but snippets can also be created through the API, through requests like this. I refresh, and it's back.
Wrapping up on adding code to a client’s theme
Liquid is a great, very performant way to render content on the storefront, and it also has a ton of contextual information about products or about the cart or the customer that's currently logged in. There’s tons of different stuff that you can use. So, definitely use that wherever you can. Hopefully the information in this article helps you when adding code to a client’s theme.
Build apps for Shopify merchants
Whether you want to build apps for the Shopify App Store, offer custom app development services, or are looking for ways to grow your user base, the Shopify Partner Program will set you up for success. Join for free and access educational resources, developer preview environments, and recurring revenue share opportunities.
Sign up