Single-page applications create a testing problem that traditional A/B tools often handle poorly. The browser loads one document, then JavaScript changes routes, content, and components without a full page refresh.
SPA A/B testing works when experiment activation follows those client-side changes. With Mida.so, you can install one tracking snippet, define a focused experiment, connect conversion events, and validate route changes before exposing the test to real traffic.
Key Takeaways
- Install Mida once in the SPA shell, not on every virtual page.
- Trigger experiments around route changes and rendered components.
- Use one primary conversion event with guardrail metrics.
- Test direct loads, client-side navigation, refreshes, consent states, and mobile layouts.
- Fix assignment, timing, and duplicate-event issues before launch.
Why SPA A/B Testing Needs a Different Setup
A traditional website usually requests a new HTML document for every page. The testing script loads again, checks the current URL, assigns a visitor to a variant, and modifies the page.
An SPA behaves differently. React, Vue, Angular, and similar frameworks load the application shell once. The router then updates the URL and renders new content inside the existing document. The browser doesn’t automatically reload the testing script during that process.
That creates three common failures:
- The experiment runs on the first route but not later routes.
- Mida assigns a visitor again after navigation.
- A variant change disappears when the framework re-renders the component.
The Mida.so platform should load once when the application starts. Your SPA then needs a clear way to tell the experiment which route or component is active.
Client-side navigation usually relies on pushState, replaceState, and popstate. The MDN History API documentation explains how those browser events work. You don’t need to reload the page to detect them.
The main rule is simple: treat a route transition as a new testing state, not a new document load.
Your experiment also needs a stable identity. A visitor who sees the control on /pricing shouldn’t switch to the variant after moving to /signup. Check that Mida persists assignment through the browser’s approved storage and consent setup.
Prepare Mida.so Before Changing the App
Start with the experiment decision. Don’t begin by editing a button or headline.
Write one hypothesis in a measurable format:
Changing the pricing page CTA from “Request a demo” to a shorter action will increase completed demo requests without reducing qualified submissions.
Choose one primary metric. For this example, the primary event could be a completed demo request. Supporting metrics could include CTA clicks, form starts, form errors, and qualified lead rate.
A useful test brief contains:
- The route or component under test
- The control and variant experience
- The primary conversion event
- Guardrail metrics
- The audience and traffic allocation
- The minimum conditions for ending the test
Next, add Mida’s installation snippet to the application shell. Place it in the shared HTML template, root layout, or framework-level document that loads once. Avoid placing it inside a page component or route-specific effect.
If the script sits inside a component, every mount can create duplicate initialization. That can produce repeated events, inconsistent assignments, and difficult-to-read reports.
Your developer should also confirm:
- The script loads in production
- Content Security Policy rules allow the required Mida resources
- Consent logic follows your privacy requirements
- The snippet isn’t blocked by an ad blocker during testing
- The application doesn’t remove or replace Mida’s container elements
Keep application logic and experiment logic separate. A marketer should be able to change traffic allocation or stop a test without requiring a new application release. A developer should control changes that affect routing, state, data integrity, or server-rendered content.
Configure an Experiment for Client-Side Routes
Use this setup sequence for a fast, controlled launch.
1. Create the experiment in Mida
Add a clear experiment name that includes the area and hypothesis. “Pricing CTA copy, demo request rate” is more useful than “Test 14.”
Set the control as the current production experience. Add the variant with one meaningful change. Don’t combine a new headline, pricing layout, form length, and navigation structure in one test unless you need to measure the complete redesign.
Assign the route or page condition. For an SPA, use the relevant path rule if Mida’s targeting options support it. Include query-string behavior when campaigns use parameters that must remain eligible.
2. Decide how the change will render
A visual editor can work for stable, server-rendered markup. SPA components need more care.
If React or Vue owns a component, a direct DOM edit may disappear after state changes. Use a stable selector and apply the change after the component exists. For larger changes, expose a small experiment variable inside the application and let the component render the chosen state.
For example, the app can read an assigned variation and render either the existing CTA label or the test label. This approach avoids a fight between Mida’s DOM change and the framework’s render cycle.
Keep selectors stable. Avoid generated class names, element positions, and selectors tied to temporary design-system output.
3. Connect the conversion event
Select the primary goal in Mida. Fire it when the user completes the action, not when the page merely displays a success state.
For a form, the event should normally occur after a confirmed successful response. For a checkout, use the completed transaction state. For a product activation flow, use the first verified activation rather than the button click.
If your team also reports events to another analytics system, keep the event names aligned. Google provides GA4 event implementation guidance, which is useful when comparing experiment data with broader product analytics.
4. Handle route changes
Test the first page load and every route that can enter the experiment.
If your router exposes a navigation callback, use it to trigger the supported Mida evaluation or experiment activation method. If the app uses browser history directly, listen for the relevant route update in your application layer.
Don’t inject the Mida script again after each route change. The script should initialize once. Only the experiment state or page evaluation should update.
Your exact activation method depends on the Mida integration available in your project. Use the method shown in Mida’s current project documentation. The implementation goal stays the same: initialize once, detect navigation, evaluate the active route, and render the assigned variation.
5. Set allocation and audience rules
Begin with a controlled percentage if the test affects revenue, signup flow, or a high-volume page. Confirm that the control remains available.
Use audience rules only when they match the hypothesis. Don’t target logged-in users, mobile users, or campaign traffic unless those groups are part of the question.
Keep the same visitor in the same variation. If assignments change between visits, investigate cookies, local storage, consent mode, cross-domain movement, and private browsing behavior.
6. Preview before enabling traffic
Use preview mode or a staging environment to inspect both variations. Test the route directly, then reach it through normal in-app navigation.
A passing visual check isn’t enough. Confirm that the event reaches Mida once, the assigned variation stays stable, and the page remains usable after a refresh.
SPA Experiment Launch Checklist
Run this checklist before making the experiment active:
- Mida loads once from the shared SPA shell.
- The control matches the current production experience.
- The variant appears after a direct route load.
- The variant appears after client-side navigation.
- Browser back and forward navigation work correctly.
- A refresh preserves the visitor’s assignment.
- The primary conversion event fires once per completed action.
- Control and variant events appear in the Mida report.
- Consent, ad-blocking, and mobile states have been tested.
- No console errors or blocked network requests affect the test.
After launch, watch the first conversions rather than reacting to the first few clicks. Early data can change quickly, especially on low-traffic routes. Check exposure counts, assignment balance, event volume, and error logs before reviewing performance.
Common Mida SPA Problems and Fixes
The variant appears on refresh but not after navigation
The experiment probably evaluates only during the initial application load. Connect the route change to Mida’s supported re-evaluation or activation method.
Also check whether the router updates the URL before or after the component renders. If Mida evaluates too early, the target element may not exist yet. Run the change after the relevant view mounts.
The variant disappears after a state update
The framework has likely rendered the original component again. Replace the direct DOM edit with application-level variation logic, or reapply the change after the component becomes available.
Don’t use long timeout chains as the main solution. They hide race conditions and create inconsistent behavior on slower devices.
Visitors switch between control and variant
Check identity persistence first. A consent banner, storage restriction, cross-domain redirect, or preview parameter can prevent the assignment from being retained.
Test the same browser across a refresh, a new route, and a return visit. Compare the assignment identifier and exposure data where your Mida setup makes those values available.
Conversion counts look too high
Look for duplicate event listeners and repeated component mounts. In an SPA, a useEffect, subscription, or route hook can run more than once.
Register analytics listeners in one controlled location. Remove the listener during cleanup when the framework requires it. Fire the conversion after the confirmed business action, not every time the success component renders.
Reports show exposure but no conversions
Check the event name, trigger location, and request status. Browser network tools can show whether the event request was sent. Then confirm that the event belongs to the same project and experiment.
A conversion may also happen on another domain. In that case, review cross-domain identity and referral behavior before judging the test.
The test changes page speed
Measure the application with and without the Mida script. Keep experiment code small and avoid loading large custom libraries for a minor UI change.
If a flicker appears, review script placement, rendering order, and the method used to hide or replace content. A test that harms the initial experience can distort the result.
Conclusion
SPA A/B testing doesn’t require a full page reload for every experiment. It requires correct initialization, reliable route detection, stable visitor assignment, and event tracking tied to real outcomes.
Install Mida once in the SPA shell. Let the router or application state control when the experiment applies. Validate direct loads, client-side transitions, rerenders, and conversion events before launch.
When those pieces work together, you can configure experiments quickly without turning every test into a new deployment project.
