Drop a lightweight script on any checkout or thank-you page to send events back to web2wave. Conversion events are forwarded to Meta, TikTok, and other ad networks via server-side APIs — no pixels on the external site.
The Web2Wave JS SDK is a small browser script you add to websites that are not hosted on web2wave (your own checkout, a third-party payment page, a thank-you page, a membership site).
From that page you can send conversion events back to web2wave. web2wave then:
- Stores them on the same user who started the quiz (
user_id) - Forwards them server-side to Meta Conversions API, TikTok Events API, and other connected ad networks
Amplitude, PostHog, and Mixpanel are not in this path. Those tools only receive browser events from the quiz / paywall itself. The SDK posts to web2wave’s server, and web2wave does not replay those server events into Amplitude / PostHog / Mixpanel.
You do not install a Meta Pixel, TikTok Pixel, or Google tag on the external website. Pixels and access tokens stay in Project → Analytics. The SDK only talks to web2wave; web2wave talks to the ad networks from the server.
This is the typical flow the SDK is built for:
- The user completes a web2wave quiz.
- They leave to an external payment page (your checkout, a PSP hosted page, a custom store).
- After a successful charge, the thank-you page calls
web2wave.purchase(...)(orweb2wave.track('Subscribe', ...)). - web2wave attributes the conversion to the original quiz session and sends it to Meta / TikTok / Google as a Conversion API event.
Inside a web2wave quiz or paywall, keep using
window.w2w. This SDK is only for external pages. For native apps, see the mobile SDKs.
Why use it
| Without the SDK | With the SDK |
|---|---|
Payment happens off-site, so web2wave never sees Purchase | The thank-you page reports Purchase / Subscribe back to web2wave |
| Meta/TikTok pixels must be installed (and allowed) on the checkout domain | No ad pixels on the checkout domain — CAPI is sent from web2wave servers |
| Browser blockers, ITP, and missing cookies break attribution | The same user_id from the quiz is sent with the event, so the funnel stays in one profile |
| You cannot optimize Meta/TikTok campaigns for off-site checkouts | Standard conversion events still train the ad accounts |
Pixels configured in web2wave (with an Access Token for server events) are enough. See Analytics Integration Guide to connect Meta, TikTok, Google, Snap, and others.
Prerequisites
- Pixels / CAPI already set up in Project → Analytics (Pixel ID + Access Token for Meta and TikTok). Browser pixels on the quiz are optional for this flow; server events are what matter for the off-site conversion.
- Your project ID — the slug from Project Settings (
project.project_id). It is the same value used inhttps://PROJECT_ID.web2wave.com. - The web2wave
user_idof the person who started the quiz. Pass it to the external page in the URL (see Identify the user).
Install
Load the SDK, then call init with your project slug:
<script src="https://app.web2wave.com/js/sdk/web2wave-sdk.min.js?v=1.0.0"></script>
<script>
web2wave.init({
projectId: 'YOUR_PROJECT_ID',
apiBase: 'https://app.web2wave.com'
});
</script>Or pass the same values on the script tag (no init() call):
<script
src="https://app.web2wave.com/js/sdk/web2wave-sdk.min.js?v=1.0.0"
data-project-id="YOUR_PROJECT_ID"
data-api-base="https://app.web2wave.com"
></script>Always set
apiBasetohttps://app.web2wave.com. Put the script beforeinit/purchasesoweb2wavealready exists.
Identify the user
Every track / purchase / setProperty call requires a web2wave user_id. If it is missing, the SDK logs a warning and does not send the request.
Resolution order:
userIdpassed toinit()/setUserId()with override (default aftersetUserId)- Query parameter —
?user_id=...(name configurable viauserIdParam) userIdfrominit()without overridewindow.user_idif the page already defines it- Value stored from a previous visit (
w2w_user_idcookie / storage)
Pass user_id from the quiz
user_id from the quizWhen you redirect from a quiz or paywall to the external site, append USER_ID to the URL:
https://checkout.example.com/pay?user_id=USER_IDOn the checkout page the SDK reads user_id automatically and persists it (cookie by default, 356 days, SameSite=Lax). Later pages on the same domain — for example /thank-you — still know who the user is.
If your links already use a different param (the paywall recipe uses web2wave_user_id), tell the SDK:
web2wave.init({
projectId: 'YOUR_PROJECT_ID',
apiBase: 'https://app.web2wave.com',
userIdParam: 'web2wave_user_id'
});Or set it in code:
web2wave.setUserId('USER_ID_FROM_QUIZ');
// alias:
web2wave.identify('USER_ID_FROM_QUIZ');Optional context from the URL is also picked up: quiz_id, quiz_version, paywall_id, paywall_version. Include them on the checkout link if you want those fields on off-site events.
See Redirect to an external paywall after price selection for wiring the paywall CTA.
Send conversion events
Purchase (most common)
purchase is a shortcut for track('Purchase', ...). Meta and TikTok treat Purchase as a standard conversion event and can optimize campaigns on it.
web2wave.purchase('29.99', {
currency: 'USD',
value: '29.99',
price_id: 'price_123',
subscription_id: 'sub_456',
eventID: web2wave.getUserId() + '_Purchase_sub_456'
});The first argument is the numeric/string value. It is copied into both event_value and event_properties.value.
Any event
web2wave.track('Subscribe', {
currency: 'USD',
value: '29.99',
price_id: 'price_123'
});
web2wave.track('StartTrial', { currency: 'USD', value: '0' });
web2wave.track('InitiateCheckout', { currency: 'USD', value: '29.99' });
web2wave.track('Lead');Use the same event names as the quiz (see Analytics Events). Names that map to standard ad-network events are forwarded to CAPI:
| SDK / web2wave event | Meta | TikTok |
|---|---|---|
Purchase | Purchase | Purchase |
Subscribe | Subscribe | Subscribe |
StartTrial | StartTrial | StartTrial |
InitiateCheckout | InitiateCheckout | InitiateCheckout |
CompleteRegistration | CompleteRegistration | CompleteRegistration |
AddPaymentInfo | AddPaymentInfo | AddPaymentInfo |
PageView | ViewContent | ViewContent |
| Other names | Custom event | Forwarded |
Pass currency + value on money events so ROAS reporting works.
eventID (for example userId + '_' + eventName + '_' + orderId) is used for Meta deduplication. Set it when the same conversion might also be sent from a quiz page or a webhook.
Automatic PageView
web2wave.init({
projectId: 'YOUR_PROJECT_ID',
apiBase: 'https://app.web2wave.com',
autoPageView: true
});Or data-auto-pageview="true" on the script tag.
End-to-end example: quiz → external checkout → Purchase
1. Paywall / quiz — send the user to your checkout with their web2wave id:
https://pay.example.com/checkout?user_id=USER_ID&quiz_id={quiz_id}2. Thank-you page — after the PSP confirms the charge:
<script src="https://app.web2wave.com/js/sdk/web2wave-sdk.min.js?v=1.0.0"></script>
<script>
web2wave.init({
projectId: 'YOUR_PROJECT_ID',
apiBase: 'https://app.web2wave.com'
});
// user_id is taken from ?user_id=... or the w2w_user_id cookie
var params = new URLSearchParams(window.location.search);
var amount = params.get('amount') || '29.99';
var orderId = params.get('order_id') || String(Date.now());
var userId = web2wave.getUserId();
web2wave.purchase(amount, {
currency: 'USD',
value: amount,
order_id: orderId,
eventID: (userId || 'unknown') + '_Purchase_' + orderId
});
</script>What web2wave does next (no extra code on your site):
- The event is stored for that
user_id(cabinet funnel analytics and UTM report). - If Meta CAPI is enabled, a Purchase event is sent to Events Manager with enhanced matching (email /
external_idwhen web2wave already has them from the quiz). - The same happens for TikTok, Google, and other ad networks you connected — using the tokens in Project Settings, not tags on
pay.example.com.
These events are not sent to Amplitude, PostHog, or Mixpanel.
To also create a subscription in the cabinet (emails, customer portal, webhooks), call POST /api/subscription from your backend in addition to the SDK event. The SDK covers cabinet analytics + ad conversions (CAPI); the subscription API covers billing records.
User properties
Attach extra fields to the same user profile:
web2wave.setProperty('plan', 'yearly');
web2wave.setProperties({
email: '[email protected]',
plan: 'yearly',
checkout_provider: 'custom'
});Email collected on the quiz is already on the profile and is used for Meta/TikTok enhanced matching. Setting it again on the thank-you page is optional.
init options
init options| Option | Default | Description |
|---|---|---|
projectId | — | Required. Project slug (project.project_id). |
apiBase | — | Always https://app.web2wave.com. |
userId | from URL / storage | web2wave user id. |
userIdParam | 'user_id' | Query parameter to read the user id from. |
userIdOverride | false | If true, userId from config wins over the URL. setUserId() sets this to true. |
useCookies | true | Persist user_id and first URL in a cookie. If false, falls back to storage. |
storage | 'session' | 'session', 'local', or 'memory' when cookies are off. |
persistUserId | true | Write w2w_user_id to storage. |
persistInitialUrl | true | Remember the first page URL (w2w_initial_url) and send it with events. |
autoPageView | false | Send a PageView event on init. |
debug | false | Log [web2wave] messages to the console. |
quizId / paywallId / versions | from URL | Attached to every event when present. |
Script data attributes (kebab-case → camelCase): data-project-id, data-api-base, data-user-id, data-user-id-param, data-use-cookies="false", data-storage, data-debug="true", data-auto-pageview="true".
Methods
All methods except getUserId return a Promise once the SDK is initialized.
init(options) / init(projectId)
init(options) / init(projectId)Call this after the SDK script has loaded, before track / purchase. Not needed if you used data-project-id on the script tag.
getUserId()
getUserId()Returns the resolved user id, or null.
setUserId(userId, options) / identify(userId, options)
setUserId(userId, options) / identify(userId, options)web2wave.setUserId('abc123');
web2wave.setUserId('abc123', { persist: true, override: true });persist(defaulttrue) — store in cookie/storageoverride(defaulttrue) — ignore a differentuser_idin the URL
track(eventName, properties, options)
track(eventName, properties, options)Sends POST /api/analytic/event/event_log.
options (all optional): eventValue, url, quizId, paywallId, paywallVersion.
purchase(value, properties, options)
purchase(value, properties, options)Same as track('Purchase', ...), with value applied as the event value.
setProperty(name, value) / setProperties({ ... })
setProperty(name, value) / setProperties({ ... })POST /api/analytic/user/property_set and .../properties_set_bulk.
enableCookies(options)
enableCookies(options)Turn cookie persistence on after init (for example after the user accepts a cookie banner).
web2wave.enableCookies();Debugging
init({ debug: true })and watch the console for[web2wave] POST /api/analytic/event/event_log.- Confirm
web2wave.getUserId()is the same id as in the quiz (Cabinet → user, or theuser_idquery param). - In web2wave, open Log of events sent using Conversion API and filter by
user_id— the off-sitePurchaseshould appear next to quiz events. Details: Advanced analytics. - Meta Events Manager / TikTok Events Manager will show a server (CAPI) event, not a browser pixel hit from
pay.example.com. That is expected.
Common issues:
| Symptom | Cause |
|---|---|
Warning user_id is missing | Checkout URL has no user_id (or your custom userIdParam), and nothing is in storage. |
Warning projectId is required | init was not called, or data-project-id is empty. |
| Event in web2wave but not in Meta | Access token / Conversion Events settings in Project → Analytics; or the event name is not in the CAPI allow-list. |
| Duplicate Purchase in Meta | Send a stable eventID and keep Send conversion event only once enabled. |
| CORS / failed fetch | apiBase must be https://app.web2wave.com. |
Related
- Analytics Integration Guide — connect Meta / TikTok / Google and map events
- Custom external payment system — create a subscription record from your own gateway
- Redirect to an external paywall — attach checkout URLs on a web2wave paywall
window.w2wJS API — events inside a quiz / paywall