🐛 [Shopify] Defer plugin init until a checkout page view, fixing double session IDs - #4981
Open
lierniel wants to merge 7 commits into
Open
🐛 [Shopify] Defer plugin init until a checkout page view, fixing double session IDs#4981lierniel wants to merge 7 commits into
lierniel wants to merge 7 commits into
Conversation
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 6685c88 | Docs | View more details | Give us feedback! |
Bundles Sizes Evolution
|
lierniel
force-pushed
the
stephan.koshcheev/RUM-18173/shopify-fix-double-session-ids
branch
from
August 26, 2026 13:28
30045a3 to
4d662d6
Compare
Collaborator
There was a problem hiding this comment.
💬 suggestion: If we want to decouple the logic for the onInit and onStart hooks, I would create two separate functions. We could keep it relatively simple:
/**
* Calls each plugin's `onInit`, and returns whether the initialization should go on: `false` if any
* plugin aborts it. Stays synchronous as long as no plugin returns a thenable.
*/
export function callPluginsOnInit(
plugins: RumPlugin[] | undefined,
parameter: { initConfiguration: RumInitConfiguration; publicApi: RumPublicApi }
): boolean | Promise<boolean> {
const results = (plugins ?? []).map((plugin) => plugin.onInit?.(parameter))
if (results.some(isThenable)) {
return Promise.all(results.map((result) => Promise.resolve(result))).then(
(resolvedResults) => !resolvedResults.includes(false)
)
}
return !results.includes(false)
}
export function callPluginsOnRumStart(plugins: RumPlugin[] | undefined, options: OnRumStartOptions): void {
for (const plugin of plugins ?? []) {
plugin.onRumStart?.(options)
}
}
lierniel
commented
Aug 26, 2026
| } | ||
|
|
||
| return new Promise((resolve) => { | ||
| let isBindingsInstalled = false |
Contributor
Author
There was a problem hiding this comment.
Add comment about it
lierniel
marked this pull request as ready for review
August 26, 2026 18:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Shopify Custom Pixel sandboxes were creating two RUM session IDs on the same page. The storefront's
Theme Liquid snippet already runs a
DD_RUMinstance for every page, while the Custom Pixel'sshopifyPluginunconditionally ran its owninit()side effects (patching sandboxed iframe APIs,wiring bindings, forcing
trackViewsManually, etc.) as soon asonInitfired — with no way to knowyet whether the page was actually a checkout page. See RFC: Preventing two SDK instances from
running at the same time
(RUM-18173).
Changes
RumPlugin.onInitcontract (packages/browser-rum-core/src/domain/plugins.ts,preStartRum.ts) soonInitmay returnfalseto abort SDK init, or aPromise<false | void>todefer it.
callPluginsMethod/runOnInitPluginsnow run plugins'onInitin order, stayingsynchronous until a plugin returns a thenable, and time out a pending
onInitafter 3s (surfacingan error rather than hanging init forever).
shopifyPlugin.onInitnow returns aPromisethat waits for the sandbox's firstpage_viewedevent and only proceeds (patches iframe APIs, wires bindings, forces sandbox-specific config) once
that event's URL matches a checkout path — so a Custom Pixel loaded on a non-checkout page no longer
spins up a second RUM instance.
initShopifyBindings'sclicked/ui_extension_erroredhandlers arenow gated the same way, via the shared
isCheckoutPagepredicate.makeShopifyRumPublicApi()init()-wrapping approach with the plugin-basedshopifyPlugin, now exposed asDD_RUM.shopifyPlugin(...)(see updatedpackages/browser-rum-shopify/README.md).Test instructions
yarn test:unit --spec packages/browser-rum-core/src/domain/plugins.spec.ts --spec packages/browser-rum-core/src/boot/preStartRum.spec.ts --spec packages/browser-core/src/tools/thenable.spec.ts --spec "packages/browser-rum-shopify/**/*.spec.ts"Checklist