Using jQuery safely: local fallbacks and tag sequences

In this article I’m going to explore two main concepts:

  • First, we’ll look at several ways you can fall back to a local version of jQuery (or indeed any other JavaScript library) when using a CDN as your primary delivery mechanism
  • Second, we’ll move onto Google Tag Manager, and look at how to safely use jQuery within your code using tag sequencing. If you want to jump straight to the GTM section of this guide, click here

Ready? Let’s go.

1. Local fallbacks for a CDN

Let’s say your website’s front-end is dependent on a library like jQuery. When using a CDN, the resource should (depending on setup) deliver from the server that’s physically closest to the user. The coverage, speed and bandwidth of the CDN’s infrastructure thus reduces the strain on your own server, decreasing page load time.

What’s more, by referencing a big CDN such as Google’s Hosted Libraries or StackPath, you can take advantage of cross-site caching. In other words, so many websites now rely on these CDNs to serve libraries like jQuery that there’s a large possibility your visitor will already have the library cached from a previous visit to another site using the same CDN.

In theory, it’s as simple as this:

<script src=""></script>

But what if the CDN goes down? This is highly unlikely, admittedly, but why leave these things to chance? What’s more, complete dependence on a CDN precludes the possibility of offline development. If your website is reliant on an external library such as jQuery, and your internet dies for the afternoon (or you enjoy coding on the tube), there’s not much you can do.

Setting a fallback

Let’s code ourselves a local fallback. That way, if our CDN of choice proves to be unavailable for whatever reason, our own webserver can supply jQuery (or ScrollMagic, or whatever else you might be using) along with the rest of our website’s files, and everything will function normally. This is the solution used in the HTML5 Boilerplate project:

<script src=""></script>
<script>window.jQuery || document.write('<script src="js/jquery-3.4.1.min.js"></script>')</script>

Here, the ‘||’ is essentially acting as an OR statement. If ‘window.jQuery’ returns FALSE (in other words, jQuery was not successfully loaded), then it executes the next statement – adding a script tag to the page that references our local copy of the library. jQuery for everyone!

Whilst sufficient for the vast majority of websites, this solution is not perfect, however. Upon discovering that the CDN is unavailable, the user’s browser could (in theory) hang for a significant length of time before giving up and falling back to the local copy. During this period, your jQuery plugins (or anything that’s called after jQuery) won’t load.

Smarter loading

Today, there are many solutions available for conditional loading of resources. One simple option is Fallback.js, a lightweight JavaScript library which allows you to set multiple failovers for your libraries and even configure shimming options. Alternatively, if you’re using a module loader like Require.js, you can use this neat shorthand:

  enforceDefine: true,
  paths: {
    jquery: [
      //If the CDN location fails, load from this location

require(['jquery'], function ($) {});

Suffice it to say, there are loads of options out there – more than we can explore within this article. Next, we’re going to move onto the subject of jQuery within Google Tag Manager.

2. Google Tag Manager and jQuery

Nowadays, fewer and fewer new projects are adopting jQuery. While it’s still a powerful library with some great features, many of the problems that it solved during its heyday (browser inconsistencies, particular of the IE-variety) are no longer an issue. The rapid evolution of ‘vanilla’ JavaScript and the introduction of powerful new features with ES6, ES2017, and so on means that many developers find less of a need for it than they used to. Other front-end libraries and frameworks are rapidly picking up steam.

Because of this, many developers find themselves in the position of needing to use jQuery only for a handful of very specific tasks. For example, there might be a specific page where you want to load a jQuery-dependent plugin using your tag management platform, on a site that doesn’t use jQuery.

In scenarios such as these, you might find yourself wondering whether it’s possible to inject jQuery on an ad-hoc basis using GTM (remembering that GTM does not load jQuery by default). As with so many is-it possible-with-GTM questions, the answer is “Yes but be careful.”

jQuery with a custom HTML tag

Simo Ahava’s written a brilliant guide to using tag sequencing in scenarios such as these. Essentially, we’re going to create a Custom HTML tag that will make an asynchronous request for the jQuery library and then use this as a setup tag (i.e. a dependency) of our jQuery-reliant code.

You’ll need to enable the Container ID and HTML ID built-in variables and then add the following code to your Custom HTML tag:

(function() {
  var el = document.createElement('script');
  el.src = '';
  el.async = true;
  el.addEventListener('load', function() { 
    window.google_tag_manager[{{Container ID}}].onHtmlSuccess({{HTML ID}})
  el.addEventListener('error', function() { 
    window.google_tag_manager[{{Container ID}}].onHtmlFailure({{HTML ID}})

Under ‘Advanced settings’, you’ll want to set ‘Tag firing options’ to ‘Once per page’ (since you’ll only want this to execute this tag once, regardless of how many tags are dependent on it). Be sure to check Simo’s guide to get a thorough understanding of the onHtmlSuccess() and onHtmlFailure() callbacks and the scenarios in which they’re necessary in tag sequencing.

Tag sequencing

Finally, we’ll need to tell GTM not to load our jQuery-dependent code until after our jQuery loader has run. Head over to your jQuery-dependent tag and add the Custom HTML tag you’ve just created as a setup tag under Tag Sequencing:

The checkbox immediately below this – “Don’t fire [dependency] if [setup] fails” – lets you prevent your jQuery-dependent code from running if the jQuery loader fails. A more elegant solution would be to craft a fallback directly into your jQuery-dependent tag, or even to migrate that functionality over to native JavaScript. But that’s beyond the scope of today’s adventure.

Thanks for reading, and happy coding!

Join the Inner Circle

Industry leading insights direct to your inbox every month.