From eef81b479fe8b43ce3579b20c6589c2eb57a47aa Mon Sep 17 00:00:00 2001 From: Nathan Booker Date: Thu, 14 Aug 2025 14:38:22 -0700 Subject: [PATCH] Add guidance for analytics scripts handling checkout prerendering --- docs/integrations/hosted-analytics.mdx | 100 +++++++++++++++++- docs/integrations/scripts.mdx | 60 +++++++++++ .../guides/manually-installing-scripts.mdx | 88 +++++++++++++++ 3 files changed, 243 insertions(+), 5 deletions(-) diff --git a/docs/integrations/hosted-analytics.mdx b/docs/integrations/hosted-analytics.mdx index 22b7ff3e6..6a061385b 100644 --- a/docs/integrations/hosted-analytics.mdx +++ b/docs/integrations/hosted-analytics.mdx @@ -377,11 +377,26 @@ function subscribeOnBodlEvents() { if (typeof window.bodlEvents.checkout.checkoutBegin === 'function') { // run the checkoutBegin function to get the payload window.bodlEvents.checkout.checkoutBegin((payload) => { - // log the event payload - console.log( - 'window.bodlEvents.checkout.checkoutBegin ~ payload', - payload - ); + // Check if page is being prerendered before tracking analytics + if (document.prerendering) { + // Defer analytics tracking until page becomes active + document.addEventListener('prerenderingchange', () => { + console.log( + 'window.bodlEvents.checkout.checkoutBegin ~ payload (after prerendering)', + payload + ); + // Now trigger your actual analytics tracking + // e.g., gtag('event', 'begin_checkout', payload); + }, { once: true }); + } else { + // Page is already active, safe to track immediately + console.log( + 'window.bodlEvents.checkout.checkoutBegin ~ payload', + payload + ); + // Trigger your actual analytics tracking + // e.g., gtag('event', 'begin_checkout', payload); + } }); } @@ -457,8 +472,83 @@ Accept: application/json } ``` +## Handling prerendered pages + +When pages are prerendered using [Speculation Rules API](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API), BODL events may fire before users actually navigate to the page. This is particularly important for checkout analytics where premature event firing can skew conversion tracking. + +### Prerendering detection for BODL events + +All BODL event handlers should check for prerendering before triggering analytics: + +```javascript +function handleBodlEvent(eventName, payload) { + if (document.prerendering) { + // Page is being prerendered - defer analytics + document.addEventListener('prerenderingchange', () => { + // Now it's safe to trigger analytics + triggerAnalytics(eventName, payload); + }, { once: true }); + } else { + // Page is already active + triggerAnalytics(eventName, payload); + } +} + +function triggerAnalytics(eventName, payload) { + // Your analytics implementation here + console.log(`Analytics event: ${eventName}`, payload); + // e.g., gtag('event', eventName, payload); + // e.g., fbq('track', eventName, payload); +} +``` + +### Updated BODL implementation with prerendering support + +Here's an updated version of the example script that includes prerendering detection: + +```javascript +function subscribeOnBodlEvents() { + // Helper function to handle prerendering + function handleBodlEvent(eventName, payload) { + if (document.prerendering) { + document.addEventListener('prerenderingchange', () => { + console.log(`${eventName} ~ payload (after prerendering)`, payload); + // Add your analytics tracking here + }, { once: true }); + } else { + console.log(`${eventName} ~ payload`, payload); + // Add your analytics tracking here + } + } + + if (!window?.bodlEvents) { + console.log('BODL not available'); + return; + } + + // Checkout events with prerendering support + if (typeof window.bodlEvents.checkout?.checkoutBegin === 'function') { + window.bodlEvents.checkout.checkoutBegin((payload) => { + handleBodlEvent('checkout.checkoutBegin', payload); + }); + } + + if (typeof window.bodlEvents.checkout?.orderPurchased === 'function') { + window.bodlEvents.checkout.orderPurchased((payload) => { + handleBodlEvent('checkout.orderPurchased', payload); + }); + } + + // Apply the same pattern to other BODL events as needed +} + +window.addEventListener('load', subscribeOnBodlEvents, false); +``` + ## Resources - [Scripts overview](/docs/integrations/scripts) - [REST Management API: Scripts reference](/docs/rest-management/scripts) - [Using Script Manager (Help Center)](https://support.bigcommerce.com/s/article/Using-Script-Manager) +- [Speculation Rules API documentation](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API) +- [Prerender pages guide](https://developer.chrome.com/docs/web-platform/prerender-pages#eagerness) diff --git a/docs/integrations/scripts.mdx b/docs/integrations/scripts.mdx index 06be996a0..789a4cea4 100644 --- a/docs/integrations/scripts.mdx +++ b/docs/integrations/scripts.mdx @@ -58,6 +58,66 @@ The following table describes the locations you can associate with Scripts API o To associate scripts with a checkout page, you need the [Modify Checkout Content OAuth scope](/docs/start/authentication/api-accounts#oauth-scopes). +## Handling prerendered checkout pages + +With the introduction of [Speculation Rules API](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API) and browser prerendering, checkout pages may be prerendered before users actually navigate to them. This can cause analytics and other event-tracking scripts to fire prematurely. + +When scripts inject into checkout pages, they should check whether the page is being prerendered to avoid triggering events before the user actually visits the page. + +### Detecting prerendering + +Use the `document.prerendering` property to detect if the page is currently being prerendered: + +```javascript +// Check if the page is currently being prerendered +if (document.prerendering) { + // Page is being prerendered - defer analytics tracking + console.log('Page is being prerendered, deferring analytics'); + + // Listen for when prerendering ends and page becomes active + document.addEventListener('prerenderingchange', () => { + console.log('Page is now active, triggering analytics'); + // Now it's safe to trigger analytics events + triggerCheckoutAnalytics(); + }); +} else { + // Page is not prerendered, safe to trigger analytics immediately + triggerCheckoutAnalytics(); +} +``` + +### Example implementation for checkout analytics + +Here's a complete example that safely handles both normal page loads and prerendered pages: + +```javascript +function initializeCheckoutAnalytics() { + function triggerAnalyticsEvents() { + // Your analytics tracking code here + // e.g., fbq('track', 'InitiateCheckout'); + // e.g., gtag('event', 'begin_checkout'); + console.log('Checkout analytics triggered'); + } + + if (document.prerendering) { + // Defer analytics until page becomes active + document.addEventListener('prerenderingchange', triggerAnalyticsEvents, { once: true }); + } else { + // Page is already active, trigger analytics immediately + triggerAnalyticsEvents(); + } +} + +// Initialize when DOM is ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializeCheckoutAnalytics); +} else { + initializeCheckoutAnalytics(); +} +``` + +For more information about prerendering detection, see the [Speculation Rules API documentation](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API) and the [prerender pages guide](https://developer.chrome.com/docs/web-platform/prerender-pages#eagerness). + ## Creating scripts for Catalyst storefronts Catalyst is BigCommerce's modern storefront framework built on Next.js. When creating scripts for Catalyst storefronts, there are several important considerations that differ from traditional Stencil themes. diff --git a/docs/storefront/catalyst/getting-started/guides/manually-installing-scripts.mdx b/docs/storefront/catalyst/getting-started/guides/manually-installing-scripts.mdx index 838ec2758..502ed5667 100644 --- a/docs/storefront/catalyst/getting-started/guides/manually-installing-scripts.mdx +++ b/docs/storefront/catalyst/getting-started/guides/manually-installing-scripts.mdx @@ -95,3 +95,91 @@ For instance, if you wanted a script for product reviews to load only on product Sometimes scripts have logic that runs each time a page is visited. If you find that the script you install is working on the first page you visit, but not the second, it's likely dependent on additional logic like this. The `