Server Side Testing
Run your A/B or Split-URL tests before any HTML leaves your server or CDN while maintaining accurate analytics in Convert.
🚀 THIS ARTICLE WILL HELP YOU:
- Know why to use Server Side Testing
- Show Supported Platforms
- Understand Pre-requisites
- Understand Patterns
- Get a Checklist
- Know how to Troubleshoot
🚀 Why Use Server-Side Testing?
-
Minimize content flash for server-rendered pages
-
Support CDN edge delivery (e.g., Cloudflare Workers, Fastly, Akamai)
-
Fully control variation logic backend-side
-
Preserve experiment tracking integrity
🧭 Supported Patterns
Pattern | Use Case |
---|---|
Cookie hand-off (_conv_sptest + Convert Tracking Script) |
You already use the Convert Tracking Script and need early rendering or redirects |
Convert JavaScript SDK (no tracking script) | You run Node.js server-side and want complete back-end control |
🔧 Prerequisites
Requirement | Cookie Hand-Off | JS SDK |
---|---|---|
Set cookies (_conv_sptest ) |
✅ | ❌ |
Node.js runtime | Optional | ✅ |
Convert Tracking Script | ✅ | ❌ |
Public SDK key | ❌ | ✅ |
Stable visitor ID | Recommended (_conv_v ) |
✅ |
🍪 Pattern A – Cookie Hand-Off (with Tracking Script)
-
Decide the
variationId
server-side -
Set a short-lived cookie:
Set-Cookie: _conv_sptest=<experiment_id>:<variation_id>; Max-Age=10; Path=/; SameSite=Lax
-
Serve the HTML or redirect accordingly
-
The Convert Tracking Script reads this cookie on load and tracks appropriately
CDN Examples:
Cloudflare Workers:
export default {
async fetch(request) {
const html = await renderVariant(varId);
const cookie = `_conv_sptest=${expId}:${varId}; Max-Age=10; Path=/; SameSite=Lax`;
return new Response(html, {
headers: {
'Set-Cookie': cookie,
'Cache-Control': 'private'
}
});
}
}
AWS Lambda@Edge:
exports.handler = async (event) => {
const req = event.Records[0].cf.request;
req.headers['set-cookie'] = [{
key: 'Set-Cookie',
value: `_conv_sptest=${expId}:${varId}; Max-Age=10; Path=/; SameSite=Lax`
}];
return req;
};
Fastly Compute@Edge and Akamai EdgeWorkers examples are similar and also supported.
⚙️ Pattern B – Convert JavaScript SDK (Node.js only)
-
Install the SDK:
npm install @convertcom/js-sdk
- Server-side split logic and redirect
import ConvertSDK from '@convertcom/js-sdk';
const sdk = new ConvertSDK({ sdkKey: 'YOUR_PUBLIC_SDK_KEY' });
await sdk.onReady();
const ctx = sdk.createContext(visitorId);
const variation = ctx.runExperience('exp-key');
return Response.redirect(
variation.id === '10002' ? 'https://site.com/new' : 'https://site.com/control',
302
); - SDK auto-tracks the visit—no cookie or tracking script needed
✅ Checklist
-
Create the experiment and obtain
experimentId
/variationId
- Choose Cookie or SDK path
- Implement server/edge logic
- (Cookie path) Set
_conv_sptest
cookie before HTML - (SDK path) Use
runExperience()
for bucketing - Ensure CDN caching respects variation logic (use
Cache-Control: private
or cache keys) - QA: Inspect network requests or SDK logs
❗Troubleshooting
Symptom | Cause | Fix |
---|---|---|
No data in reports (cookie path) | Cookie not present before tracking script | Ensure it’s set in the first response |
Visitor switches variation | You overwrote _conv_v |
Never touch _conv_v |
Duplicate bucketing | SDK run + manual call | Use { enableTracking: false } |
Wrong HTML | CDN cache doesn’t vary by cookie | Use Cache-Control: private or vary by _conv_sptest |
TL;DR:
Use cookie hand-off for quickest implementation with tracking script.
Use Convert SDK for full backend control, ideal for Split-URL or headless setups.