Troubleshooting
When variants do not appear, “stick,” or disappear in SPAs, work systematically: check assignment first, then markup/keys, then session and routing behavior.
Common issues and solutions
Section titled “Common issues and solutions”/* Add CSS to <head> to reduce flicker */.ab-test-loading { visibility: hidden !important;}<body class="ab-test-loading"> …</body>// Make visible after variant applicationdocument.body.classList.remove("ab-test-loading");Combine this with an HTML fallback so users without JS or on a slow network still see content. See HTML variants → Anti-patterns.
// Lazy loading for heavy variantsif (window.usertrax.getVariant("heavy_test") === "variant_with_video") { // Only load video when necessary loadVideoAssets();}Do not eager-load heavy assets in both variants — fetch them only for the assigned variant.
// Debug information in consoleconsole.log("Active A/B tests:", window.usertrax.getAssignments());
// Check test assignment in sessionStorageObject.keys(sessionStorage).forEach((key) => { if (key.startsWith("usertrax_ab_")) { console.log(key, sessionStorage.getItem(key)); }});Variant not visible
Section titled “Variant not visible”API available?
typeof window.usertrax?.getVariant; // "function"Otherwise the script has not loaded yet — see JavaScript API → Queue.
Assignment present?
window.usertrax.getAssignments();// expected e.g. { button_color_test: "variant_red" }Empty? Is the test active? Does URL targeting match the current page? Domain/API key correct?
Match keys
data-usertrax-ab-test-group= test key,data-usertrax-ab-test-variant= variant key — exact match.Inline styles
Non-assigned variants should start with
style="display: none"; the assigned one hasdisplaycleared by the tracker. Your own CSS withdisplay: none !importantcan override that.Fallback vs. assignment
Once assigned, the tracker shows only the matching variant — even if another element has
data-usertrax-ab-test-fallback.
Sticky assignment
Section titled “Sticky assignment”Assignments are stored in sessionStorage under usertrax_ab_<test_key> and stay stable for the session — that is intentional, so users do not jump between variants.
To re-roll randomly (testing only):
// Remove all usertrax A/B keys and reloadObject.keys(sessionStorage) .filter((k) => k.startsWith("usertrax_ab_")) .forEach((k) => sessionStorage.removeItem(k));location.reload();Or use a private window / another browser. Traffic-split changes mainly affect new sessions, not ones already assigned.
SPA routing
Section titled “SPA routing”The tracker listens for client-side navigation and can re-apply session / element visibility. Still, common pitfalls:
| Problem | What to do |
|---|---|
| New route renders variant markup only after navigation | Set attributes on the new DOM; call window.usertrax.applyElementVisibility() if needed |
| Test is URL-targeted; SPA changes path without reload | Ensure the URL pattern matches the client route; re-check assignment after navigation |
| Framework hydrates and resets styles | Re-apply visibility after hydration, or drive variants via framework state + getVariant |
getVariant called too early in setup hooks | Wait until the method exists (see JavaScript API) |
// After your own route change / dynamic insertif (typeof window.usertrax?.applyElementVisibility === "function") { window.usertrax.applyElementVisibility();}Technical details: session management
Section titled “Technical details: session management”- A/B test assignments are stored in
sessionStorage(usertrax_ab_<test_key>) - Sessions remain active for 30 minutes after last activity
- After expiry / a new session, a different variant may be assigned
- Conversions automatically receive
ab_test_datawith current assignments - HTML elements with A/B attributes inserted after load are handled via a MutationObserver in fallback mode first, then switched correctly once tests are loaded
For broader session and attribution questions: Sessions & Attribution.