ProveLift help center
Everything you need to run trustworthy A/B tests — from pasting the snippet to reading a statistically sound result. Follow it top-to-bottom the first time, then use it as a reference.
Overview
ProveLift is a full A/B testing platform: you change something on your site for a slice of visitors, measure whether it moves a goal, and let real statistics tell you if the difference is trustworthy.
The whole system is three moving parts:
The snippet
One async script tag on your site. It fetches your live experiments, assigns each visitor a variant, applies the changes flicker-free, and reports events.
The dashboard
Where you create experiments, edit variants visually, define goals and targeting, and watch results roll in.
The stats engine
Frequentist + Bayesian analysis, sample-ratio checks and guardrails that tell you when — and only when — you have a winner.
Quickstart
Five steps from zero to a running experiment.
- Add your domain. In the dashboard go to
Domains → Newand enter the site you want to test (e.g.shop.example.com). - Install the snippet. Copy the one-line tag from
Integrationsand paste it before</head>on every page. See Install the snippet. - Verify. ProveLift checks your site is reachable and the snippet is live. A green check means you’re ready.
- Create an experiment. Click
New experiment, name it, add a variation (the visual editor opens on your real page), and pick a goal. - Start it. Hit Start. Visitors are split, and Results begin filling in within seconds.
Install the snippet
A single asynchronous script tag. Your unique SNIPPET_ID is baked into the exact tag shown on your Integrations page — copy it from there.
<script src="https://provelift.com/snippet/YOUR_SNIPPET_ID.js" async></script>Place it as high in <head> as possible. The snippet ships with a built-in anti-flicker loader: it briefly hides the page, applies your variant, then reveals — so visitors never see the original flash before the change. The higher the tag, the shorter that moment.
Optional configuration
The snippet auto-detects your ID from its own src, so no config is required. If you want to hook in, define window._ab before the script tag:
<script>
window._ab = {
debug: true, // verbose console logging
onReady: function (ab) { // runs once variants are applied
console.log('Variant:', ab.getVariant('Homepage hero'));
}
};
</script>
<script src="https://provelift.com/snippet/YOUR_SNIPPET_ID.js" async></script>Verify it’s working
Open your site, then your browser console. With debug:true you’ll see [ProveLift] ready! and a 200 POST to /api/v1/track. In the dashboard, the domain’s status turns green and Visitors starts counting.
Domains & verification
A domain (also called a project) is one website. Each has its own snippet ID, experiments, goals and team access.
Verification
After adding a domain, ProveLift confirms two things: that the domain resolves and responds, and that the snippet is actually present on the page. Both are one click and re-runnable — you’ll see clear instructions in the domain’s row if something’s missing.
First-party tracking (optional)
For maximum resilience against ad-blockers and tracking-prevention, you can serve the snippet and collect events from a subdomain of your own site (e.g. ab.example.com) instead of the ProveLift host. Add a CNAME and ProveLift provisions the certificate automatically. Ask in support to enable it for your plan.
Experiments
An experiment splits your traffic between a control (the original) and one or more variants, then measures which converts your goal best.
What you can test
- A/B — control vs one variant.
- A/B/C… — control vs several variants at once; traffic splits evenly by default, adjustable per variant.
- Split URL / redirect — send a share of visitors to an entirely different page (set the variant’s target URL).
Lifecycle
Start moves a draft to Running. Pause stops assigning new visitors while keeping data. Complete ends the test for good. You can Duplicate any experiment to iterate on a winning idea.
Variants & traffic split
Every experiment has a control plus your variants. Each gets a traffic weight that determines its share of visitors.
- Deterministic bucketing. A visitor is hashed to a variant and stays in it on every visit — no flip-flopping. The same logic runs client-side and server-side, so both agree.
- Weights. Default is an even split. Set e.g. 90/10 to limit exposure to a risky change.
- Control. Exactly one variant is the control (baseline) — results are always reported relative to it.
Visual editor
Change your page without writing code. “Add variation” opens your real, live page with an editing toolbar — no fragile iframe.
How it works
- From an experiment, click Add variation (or edit an existing one).
- ProveLift opens your page with the editor booted by the installed snippet, authorized by a short-lived token.
- Click any element to edit text, change styles, hide, move, or replace an image. You can also drop in custom CSS/JS for full control.
- Save. Your changes are stored as the variant’s payload and applied to visitors when the experiment runs.
Font size
Color
Hide
Custom CSS
Client-side vs server-side delivery
Two ways to apply a variant. Pick per experiment.
| Client-side (default) | Server-side |
|---|---|
| The snippet applies DOM/style changes in the browser. | Your backend asks ProveLift which variant a visitor gets, then renders that HTML itself. |
| No code — use the visual editor. | Zero flicker, works for prices/logic, but you write the rendering. |
| Best for copy, layout, styling, CTAs. | Best for pricing, algorithms, back-end flows. |
Server-side: get an assignment
Call the assign endpoint from your backend with a stable visitor_uid (e.g. a first-party cookie). Exposure is recorded automatically; send conversions later via /v1/track.
curl -X POST https://provelift.com/api/v1/assign \
-H "X-ProveLift-Project: YOUR_SNIPPET_ID" \
-H "Content-Type: application/json" \
-d '{ "project_id": "YOUR_SNIPPET_ID", "visitor_uid": "u_8f3a...", "url": "https://example.com/pricing" }'{
"visitor_uid": "u_8f3a...",
"assignments": [
{
"experiment_id": "e2c1...",
"experiment": "Pricing page test",
"variant": { "key": "b", "name": "Annual-first", "is_control": false, "payload": { … } }
}
]
}Read variant.key / variant.payload and render accordingly. See the full REST API reference.
Targeting rules
Decide who and where an experiment runs. All rules must pass for a visitor to be included.
| Rule | What it matches | Example |
|---|---|---|
| URL | Which pages the test runs on — exact, contains, starts/ends with, or regex. | contains /pricing |
| Device | Device type — chosen from a dropdown. | mobile, desktop, tablet |
| Browser | Visitor’s browser. | chrome, safari |
| Audience | Traffic source, new vs returning, query parameters, and more. | utm_source = google |
mobil and silently match nobody.Scheduling
Give an experiment a start and/or end date. It goes live and stops automatically — useful for campaigns and to avoid the temptation to peek and stop early.
- Set a start to launch during a promo window.
- Set an end to enforce a pre-committed run length (the honest way to run a test).
- Leave both empty to control it manually with Start / Pause / Complete.
QA / preview mode
See any variant exactly as a visitor would — including drafts and paused tests — without polluting your data.
Use the Preview action on an experiment to generate a link, or append the parameter yourself:
https://example.com/?ab_preview=EXPERIMENT_ID:VARIANT_ID
- The chosen variant is forced, bypassing targeting and traffic split.
- Nothing is tracked — no exposures, no conversions.
- A small badge appears bottom-left so reviewers know they’re in preview.
- For draft/paused experiments, the dashboard’s Preview link adds a signed token (
&ab_pt=…) so they’re allowed through.
Goals
A goal is the thing you’re trying to improve. An experiment has one primary goal (the decision-maker) and any number of secondary goals you monitor alongside it.
| Type | Fires when… | Config |
|---|---|---|
| Click | A visitor clicks an element matching a CSS selector. | selector, optional text/URL contains |
| Page view | A visitor reaches a URL (e.g. a thank-you page). | URL pattern + match type |
| Custom event | Your code calls ProveLift.goal('name'). | event name |
| Revenue | A purchase is reported, with an amount. | event name, value + currency |
| GA4 import | Pulled from a Google Analytics 4 event you already track. | GA4 event name (via connect) |
The goal() API
For custom-event and revenue goals, fire the conversion from your own code with one call.
// A simple custom-event conversion ProveLift.goal('newsletter_signup'); // With extra properties ProveLift.goal('add_to_cart', { product_id: 'SKU-42', category: 'shoes' });
goal() just dispatches an event the snippet listens for — it’s safe in click handlers, on links, and before navigation. If the snippet isn’t ready yet, calls are queued.Calling it from a link that navigates away
Because it’s non-blocking, you can call it inline on outbound links without breaking the click:
<a href="/checkout" onclick="ProveLift.goal('start_checkout')">Checkout</a>The event is sent via a background beacon that survives the page unload, so conversions on navigation aren’t lost.
Revenue tracking
Report an order amount so ProveLift can compare revenue per visitor between variants — not just conversion rate.
Call goal() on your order-confirmation page with a revenue value:
ProveLift.goal('purchase', {
revenue: 129.90,
currency: 'USD',
transaction_id: 'ORDER-10023'
});Revenue goals surface total revenue, revenue per visitor, and average order value per variant in Results, and are included in exports.
Reading results
The Results tab shows each variant’s visitors, conversions, conversion rate, uplift versus control, and how confident the engine is.
What each number means
- Visitors — unique people bucketed into each variant (not raw page loads; repeat visits count once).
- Conversions — unique visitors who hit the goal.
- Conversion rate — conversions ÷ visitors.
- Uplift — relative change versus control.
- Confidence / probability — how sure the engine is the difference is real, not noise (see below).
Statistics explained
ProveLift runs two complementary analyses and a set of data-quality guardrails, then boils them down to one recommendation.
Frequentist & Bayesian
- Frequentist — the classic significance test. “Confidence” ≈ how unlikely this result is if the variants were actually identical. 95%+ is the common bar.
- Bayesian — “probability to beat control,” plus the expected size of the improvement. More intuitive for decisions (“there’s a 97% chance B is better, by about +2 pp”).
Both point the same way on a genuine effect; when they disagree, you don’t have enough data yet.
Sample-ratio mismatch (SRM)
If you configured a 50/50 split but the delivered traffic is, say, 60/40, something is broken — a redirect, a cache, a tag-manager race. SRM detection catches this and overrides any winner call, because the data can’t be trusted until it’s fixed.
The recommendation
| Verdict | Meaning |
|---|---|
| 🏆 Implement winner | A variant is convincingly better on the primary goal, the split is healthy, and there’s enough data. Ship it. |
| ⏳ Keep testing | Trending, but not yet conclusive. Let it run. |
| 🔧 Fix data issues | An SRM or guardrail tripped. Results are untrustworthy until resolved — don’t act on them. |
Reports & sharing
Export or share results without giving people dashboard access.
- PDF report — a polished summary with the hypothesis, every goal’s breakdown, conversion-rate bars and the verdict. Great for stakeholders.
- Excel export (.xlsx) — a styled workbook with per-variant, per-goal numbers (winner and control rows highlighted) for your own analysis.
- Shareable link — a read-only public results page at
/r/<token>. Click Copy to grab it; revoke any time.
Integrations overview
The Integrations page (in the dashboard) is your hub: pick a domain, copy its snippet, and install via a ready-made plugin or a native connection.
🛒 E-commerce plugins
One-click modules for WooCommerce, PrestaShop, Magento 2, Magento 1 and Shopify — snippet + revenue tracking baked in.
🏷️ Google Tag Manager
Connect once; ProveLift creates the tags in your container for you.
📈 Google Analytics 4
Connect with OAuth, import GA4 events as goals, and split GA4 conversions by variant.
🔔 Webhooks & email
Get notified — per domain — when an experiment reaches a winner or a guardrail trips.
E-commerce plugins
Download a plugin from Integrations with your Snippet ID pre-filled, or install the generic build and paste the ID in the plugin's settings. Either way the snippet and automatic purchase tracking go live on install.
| Platform | Install |
|---|---|
| WooCommerce / WordPress | Plugins → Add New → Upload the .zip → Activate. Purchases fire on the WooCommerce thank-you page. (WordPress.org-ready, includes a readme.txt.) |
| PrestaShop | Modules → Upload a module → drop the .zip → Install. |
| Magento 2 / Adobe Commerce | Unzip to app/code/ProveLift/Tracking, then module:enable → setup:upgrade → cache:flush. |
| Magento 1 (legacy) | Community-codepool module — unzip into your Magento root and clear cache. |
| Shopify | Paste the snippet in theme.liquid, and the revenue snippet in Settings → Checkout → Order status page → Additional scripts (copy-paste block provided on the page). |
ProveLift.goal(...) calls and click/page-view goals work exactly as on a hand-coded site — the plugins add automatic purchase tracking on top.Plugin settings
Every plugin has a settings screen — WooCommerce/WordPress: the ProveLift menu; PrestaShop: Modules → ProveLift → Configure; Magento 2: Stores → Configuration → ProveLift; Magento 1: System → Configuration → ProveLift. There you can:
- Confirm your Snippet ID — a “Find your Snippet ID” link jumps straight to this domain's page in ProveLift so you can copy it.
- Toggle Apply price tests to enable/disable server-side price testing.
Price testing e-commerce
A/B test your product prices — not just the page. Because the change happens server-side inside your store plugin, the price the shopper sees is the price they’re charged, all the way through cart and checkout. Most client-side tools can’t do this.
How it works
- You define a control price and one or more challenger prices for a product in Price tests (dashboard).
- Each visitor is assigned a price server-side and stays on it (sticky, deterministic).
- Your store plugin applies that price through the platform’s real pricing layer — product page, listing, cart, checkout all agree.
- On purchase, the plugin reports the order against the visitor’s assigned variant, so results are exact.
Set one up
- Install the e-commerce plugin (WooCommerce, PrestaShop or Magento) and enable “Apply price tests” in its settings.
- In the dashboard go to Price tests → New: pick the domain, enter the product ID, the current price, and your challenger price(s).
- It’s created as a draft. Review, then Start.
- Watch Results — visitors, conversion rate, and revenue per variant.
Google Tag Manager
Two ways: a native connect (recommended) or a container file import.
Native connect (recommended)
- On Integrations → Google Tag Manager, click Connect Google Tag Manager and authorize with Google.
- Pick your account and container.
- Click Install ProveLift tags — ProveLift creates the snippet tag (All Pages) and a purchase tag directly in your container.
- Open GTM, review, and Submit & Publish to go live.
Container file (fallback, no OAuth)
Prefer not to connect? Download the container JSON and import it in GTM under Admin → Import Container.
Google Analytics 4
Connect GA4 with OAuth (no service-account keys) to import events as goals and slice GA4 conversions by variant.
- On the domain’s settings, click Connect Google Analytics and approve on Google.
- Pick the GA4 property.
- Add a goal of type GA4 import and choose one of your existing GA4 events.
Splitting GA4 conversions by variant
On exposure, the snippet pushes a parameter ab_variant_pro (value <experimentId>:<variantKey>) to gtag and the GTM dataLayer. To break GA4 reports down by variant, create a GA4 custom dimension (Event scope, parameter ab_variant_pro).
Webhooks & email alerts
Be told the moment something important happens — a winner is found, a guardrail trips, an experiment starts or ends.
- Webhooks — ProveLift POSTs a JSON payload to your URL for the events you subscribe to. Deliveries are logged and retryable, and you can send a test.
- Email notifications — the same alerts, delivered to the recipients you choose.
- Per-domain scoping — tie a webhook or email alert to a specific domain, or leave it unscoped to cover all of them.
// Example webhook payload
{
"event": "experiment.winner_found",
"experiment": { "id": "e2c1...", "name": "Homepage hero" },
"winner": { "variant": "Variant B", "uplift": 0.96, "confidence": 0.97 }
}Team & invitations
Invite teammates to a workspace and control what they can see.
Inviting
- Go to Team → Invite, enter an email and a role, and optionally restrict them to specific domains.
- They receive an email with Accept and Decline buttons.
Accepting
- Existing users just confirm with their password — no re-registration.
- New users set a name and password right on the invitation page (a lightweight sign-up, not the full flow). The acceptance page shows exactly what they’re joining and as which email.
- Decline stops reminder emails, and the declined status is visible to admins on the Team page.
Billing & plans
Plans differ by monthly tracked visitors, number of domains, team seats and features. Manage everything from the dashboard.
- Usage — a dashboard widget shows where you are against your plan’s limits; you’re warned by email before you hit them.
- Upgrade / downgrade — handled through Stripe’s secure checkout and billing portal.
- Invoices — download any invoice as a PDF from Billing.
See Pricing for the current plan lineup.
JavaScript API reference
Everything the snippet exposes on the global ProveLift object.
| Call | Description |
|---|---|
ProveLift.goal(name, detail?) | Fire a custom-event / revenue conversion. Non-blocking. detail is optional metadata (e.g. { revenue, currency, transaction_id }). |
ProveLift.getVariant(name) | The variant object this visitor is in for the named experiment, or null. |
ProveLift.isInExperiment(name) | true if the visitor is bucketed into that experiment. |
ProveLift.track(event, props?) | Low-level event send (goals normally cover this for you). |
window._ab.onReady(ab) | Callback run once variants are applied — safe place to read getVariant. |
window._ab.debug = true | Verbose console logging. |
window._ab = {
onReady: function (ab) {
if (ab.isInExperiment('Pricing test')) {
var v = ab.getVariant('Pricing test');
console.log('This visitor sees:', v.name);
}
}
};REST API reference
The snippet uses the public tracking endpoints under /api/v1. To pull your own data — domains, tests, and results — create a read-only API key and call the same base URL.
Public (snippet) endpoints
GET/api/v1/config/{snippet_id}
Returns the live experiment configuration the snippet needs (experiments, variants, goals, targeting). Cached and CDN-friendly.
POST/api/v1/track
Records an event (exposure or conversion). Sent by the snippet as a “simple” request (no preflight). Include the project via the X-ProveLift-Project header or in the body.
{
"project_id": "YOUR_SNIPPET_ID",
"visitor_uid": "u_8f3a...",
"experiment_id": "e2c1...",
"variant_id": "v_b...",
"event_type": "conversion",
"goal_id": "g_purchase...",
"properties": { "revenue": 129.90, "currency": "USD" }
}POST/api/v1/track/batch
Send multiple events in one request (used for buffered/beacon flushes).
POST/api/v1/assign
Server-side variant assignment for server-side delivery. See the example above.
Read API (API key)
Pull your workspace’s domains, tests, and results programmatically. Create a key in the dashboard under Settings → API Keys (choose Secret), copy it once, and send it as a bearer token:
curl https://provelift.com/api/v1/projects \ -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \ -H "Accept: application/json"
GET your data; they never create, change, or delete. Each key is scoped to the workspace it was created in. Rate limit: 100 requests/min. Keep sk_ keys server-side only.Domains & projects
GET/api/v1/projects — list your domains/projects (with experiment counts).
GET/api/v1/projects/{id} — a single project incl. snippet ID and verification status.
Tests (experiments)
GET/api/v1/projects/{projectId}/experiments — all tests in a project.
GET/api/v1/experiments/{id} — one test with its variants and goals.
Results (per test)
GET/api/v1/experiments/{id}/stats — visitors, conversions, uplift and significance per variant.
GET/api/v1/experiments/{id}/stats/timeseries — daily breakdown for charts.
GET/api/v1/experiments/{id}/stats/segments — results split by segment.
GET/api/v1/experiments/{id}/health — sample-ratio (SRM) and data-quality checks.
GET/api/v1/experiments/{id}/export — full results as a downloadable report.
Example — results for one test:
curl https://provelift.com/api/v1/experiments/EXPERIMENT_ID/stats \ -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \ -H "Accept: application/json"
Troubleshooting
“Visitors: 0” — nothing is being counted
- Confirm the snippet is on the page (View Source → search your Snippet ID) and the experiment is Running.
- Open the console with
?debug on (window._ab.debug = true): you should see[ProveLift] ready!and a 200 POST to/api/v1/track. - A non-200 on
/track, or a CORS error, means the request is being blocked — check that you’re on the domain you registered and that no security plugin is stripping the request. - Make sure the visitor actually matches your targeting (URL, device, audience) — over-tight rules can exclude everyone.
The original flashes before the variant (flicker)
- Move the snippet higher in
<head>, above render-blocking scripts. - Don’t load it lazily or after your app mounts — the anti-flicker must run before paint.
“Fix data issues” / SRM warning
Delivered traffic doesn’t match the configured split. Common causes: a caching layer serving one variant more, a redirect loop, or a tag-manager race. Fix the cause, then the results become trustworthy again. Don’t act on data while this is flagged.
Verification won’t turn green
- The snippet must be present on the exact domain you registered (including www vs non-www).
- If your site is behind auth or geo-blocking, our checker may not reach it — contact support and we’ll verify manually.
FAQ
Will the snippet slow down my site?
It loads asynchronously and is small. The only visible moment is the brief anti-flicker hide, which is milliseconds when the tag is high in the head.
Can I run several experiments on one page?
Yes. Each visitor is bucketed independently per experiment. Be mindful of overlapping changes on the same element.
Does a visitor always see the same variant?
Yes — assignment is deterministic and sticky per visitor, and consistent between client-side and server-side delivery.
How long should I run a test?
Until the engine reaches confidence and you’ve covered at least one or two full business cycles (typically 1–2 weeks) to avoid day-of-week bias. Pre-commit to a run length and don’t stop early.
Do custom events work through the e-commerce plugins?
Yes — the plugins install the full snippet, so ProveLift.goal(...), click goals and page-view goals all work. The plugins add automatic purchase tracking on top.