Note: This is in early development. Please contact us if you wish to use it so we can help set it up and test.
This module enables you to mark scripts and links to be loaded after a delay. They are controlled by special attributes that define how they should load. Currently, it only detects scripts and links added before DOMContentLoaded.
Note: Page Lightning is not present on checkout pages. Do not mark up scripts to be delayed on those pages.
If it encounters any errors, it is designed to load the scripts instantly and log the error in the console. These ‘Page Lightning’ errors can be seen in The Tag Rocket Report.
Examples of its use:
- Delay the loading of a chatbot
- Delay tracking code
- Stop tracking code from running until the user actually sees the page
- Remove render-blocking requirements like jQuery
Inline Scripts
<script nonce="{{nonce}}" type="late-loading" data-late-loading-needs="load">
// Script that runs on load
</script>
The type is set to ‘late-loading‘ to give the app control of the script. data-late-loading-needs defines what is needed before it runs. In this case, the load event.
External Scripts
<script nonce="{{nonce}}" data-late-loading-src="/script-on-page-visible.js" data-late-loading-needs="pageVisible"></script>
In this case, what would have been in the src attribute is now in the data-late-loading-src attribute to prevent it from being requested immediately.
This script is requested when the page is visible. This can be useful to stop scripts from running when a page is loaded in the background, like with the Speculation Rules prerender. You don’t want tracking scripts to run if the user never actually looks at the page.
Links
<link data-late-loading-href="..." data-late-loading-delay="1000" rel="..." ></link>
What would have been put in the href attribute is now in the data-late-loading-href attribute to prevent it from being requested immediately.
In this example, data-late-loading-delay is used to delay loading the resource by 1 second.
Late Loading Attributes
If no attributes are provided, the resource will be enabled straight away.
| data-late-loading-src | Use this in place of the src attribute for external scripts. |
| data-late-loading-href | Use this in place of the href attribute for links. |
| data-late-loading-needs | Indicates what must happen before it can be loaded. Possible values: pageVisible, dcl, load, saveData |
| data-late-loading-delay | Once all needs are met, you can add a further delay in milliseconds:data-late-loading-delay="1000" |
| data-late-loading-visible | A CSS selector of resources to load after DCL |
| data-late-loading-preload | Delay the execution but not loading of a script |
| data-late-loading-emergency-load | Set to false, this will exclude a script from being emergency loaded |
| Custom Needs | You can create your own “Needs” functions to suit your purpose |
data-late-loading-needs
The data-late-loading-needs attribute indicates what must happen before it can be loaded. The following needs are built in:
- pageVisible = the user has seen the page
- dcl = the DOMContentLoaded event has fired
- load = the load event has fired
- saveData = the device is asking you to minimise network use because it is expensive
Need checks are case-insensitive and ignore dashes, so pagevisible, page-visible, and PageVisible all match.
Multiple needs can be specified. If you separate them with spaces, AND logic is applied, all the needs are required for the script to run. This example requires the page to be visible, and the load event has fired:
data-late-loading-needs="pageVisible load"
More complex logic can be used, with a JavaScript like syntax using &&, ||, () and ! for not. For example:
data-late-loading-needs="pageVisible && (dcl || load) && !saveData"
It’s possible to define a networkSpeed using operators. The speeds are based on an equivalence to mobile network speeds and must be integer values, and can optionally end with ‘g’. As of Feb 2026, the browser will only report up to 5g even if the network is much faster. e.g. you may want to use one script for slow or expensive networks:
data-late-loading-needs="networkSpeed <= 4g || saveData"
And a different script for fast networks:
data-late-loading-needs="(networkSpeed > 4g || networkSpeed == null) && !saveData"
Note the extra null check, as many browsers do not provide network speed.
data-late-loading-visible
Contains a CSS selector. On DCL, it starts monitoring elements that match that selector. If any become visible it can be enabled. E.g., “.video” could be used to load video resources as the video element becomes visible.
data-late-loading-visible=".video"
This does not currently deal with dynamically added elements. Only element present when the documents content is initially loaded (DCL).
data-late-loading-preload=”true”
You may want to just delay a resource from being run to avoid using the CPU early on in the rendering process. But you’re happy to let it start loading earlier. In this case, preload is for you.
If this attribute is present and not set to false, a preload link will be added to the page as soon as the script or link is processed by Page Lightning. This way, you can keep the script/link loading early, but delay its execution.
You can also add preloads or even preconnects via Page Lightning’s Early Loading module.
data-late-loading-emergency-load=”false”
If there is a major error in the main script, a backup footer script starts loading the late load scripts using simple code, minimising the chance of failure.
The above attribute, set to false, can be used to exclude a script from this emergency loading.
This comes in handy in scenarios where the script to be loaded varies, say, by the network speed or saveData. You can pick one for the emergency load and add this attribute to the others.
<script nonce="{{nonce}}" data-late-loading-src="small.js" data-late-loading-needs="saveData" data-late-loading-emergency-load="false"></script>
<script nonce="{{nonce}}" data-late-loading-src="big.js" data-late-loading-needs="!saveData"></script>
Custom Needs
It is possible to invent your own needs and say when they have been met. To set it up, place this code above any scripts in base.html. This is so it will still work, even if a script is before Page Lightning.
<script nonce="{{nonce}}">
if(!window.PageLightning)window.PageLightning={needsMetArray:[],needsMet:function(){this.needsMetArray.push(arguments)}};
</script>
Now, when you have determined that a need has been met, call the PageLightning.needsMet() function with the name of the need.
A simple example is to enable using page types as a need. Place this after the above script:
<script nonce="{{nonce}}">
PageLightning.needsMet('pageType-{{page_type}}');
</script>
Now, you could restrict a script to a specific page:
data-late-loading-needs="pageType-product"
Custom needs can also be used to sequence non-blocking scripts. Say you’re using jQuery, which is normally a blocking script that slows down page load. You could make it load asynchronously so it does not block, then specify that other scripts need it loaded before they run. First, we modify the jQuery script to be async and say that the jQuery need is met once it has loaded:
<script nonce="{{nonce}}" async src=".../jquery.min.js" onload="PageLightning.needsMet('jQuery');"></script>
Note that the onload attribute is run after the script has been loaded and run. At that point jQuery will be available for use.
Then we add that need to any script that needs jQuery. e.g.
<script nonce="{{nonce}}" data-late-loading-src="..." data-late-loading-needs="jQuery"></script>
There may be times when a need is no longer met. For them, prepend the needs name with a “-“. e.g.
PageLightning.needsMet('-consent-analytics');
Or you can specify more than one need being met or not:
PageLightning.needsMet('consent-targetingAdvertising', '-consent-analytics');
Tag Rocket Custom Needs & Consent
When complying with users’ consent choices, you often have scripts that should not run until certain consents are granted. If you use Tag Rocket or the Script Manager, consent is already managed. But not for scripts outside that, like directly in the theme.
With this Tag Rocket to Page Lightning script, which uses the Tag Rocket API, Tag Rocket will indicate that custom needs are met/lost as consents are granted or denied:
- consent-established = indicates that the following needs have been correctly set
- consent-targetingAdvertising
- consent-analytics
- consent-functional
- consent-adPersonalization
- consent-adUserData
Say you have an advertising script where you also want to avoid tracking if the user does not see the page:
<script nonce="{{nonce}}" data-late-loading-src="..." data-late-loading-needs="consent-established consent-targetingAdvertising pageVisible"></script>
Note that it can take time to establish consent states (DCL), so a natural delay is built in. The consent-established need is used to ensure the correct consent needs have been set before the consent states are assessed.