Browse the docs

Tracking & attribution

Measurement for an always-on performance stack: one first-party script ties site visits, conversions, and revenue back to your campaigns, with no per-channel pixels to configure.

Installing the tag

The Tracking page in the app gives you a personalized snippet with your site token. It goes in your site’s <head>:

<script async src="https://waverunner.adwave.com/t/YOUR_SITE_TOKEN"></script>
  • One tag per website: each business in your account has its own snippet, conversion rules, webhook, and settings. Run more than one site? Use the switcher on the Tracking page to pick the right one.
  • The tag is SPA-aware: it tracks route changes in single-page apps automatically.
  • Recommended settings (per website, on by default): automatic capture of clicks and form submits, Form conversions (success-gated signup/lead/subscribe), and origin enforcement. Turning any of these off asks you to confirm the impact on Autopilot and tracking. You can restore all recommended settings in one click.

Step-by-step install guides, written for non-technical readers:

Defining conversions

The easiest way to set up conversions: on the Tracking page, describe what counts as a win in plain language (“a purchase: people land on an order confirmation page”). Waverunner analyzes your site’s recent traffic and proposes evidence-backed rules you approve with one click. It also watches for conversion-looking pages on its own and asks whether to track them. Nothing is ever tracked without your say-so.

Under the hood, conversions come from four places:

  • Conversion rules: match a URL (like a thank-you page) and Waverunner records the conversion, no code needed. Approving a suggestion creates one of these; you can also add them manually. Rules are per website: a rule you add for one site never fires on another. Prefer confirmation pages over form-entry URLs like /signup.
  • Form conversions: with autocapture + Form conversions enabled, a successful marketing form submit (HTTP 2xx with success UI, or a thank-you navigation) records signup, lead, or subscribe, not every bare submit or form-page visit. No thank-you URL required.
  • The tag API: fire a conversion event from your frontend with a value, currency, and order ID (order IDs de-duplicate automatically).
  • Server-side webhooks: a per-website webhook URL accepts conversions from your backend, with ready-made recipes for Shopify, Stripe, WooCommerce, and Zapier.

What a win is worth

Cost per conversion works as soon as conversions count. Return on ad spend (ROAS) needs a dollar value on those wins. We never invent a platform default: until you set a value, ROAS shows an honest dash, and Autopilot still optimizes for cost per conversion.

  • Purchases: pass the real order amount in a track call, or connect Shopify / WooCommerce / Stripe so the webhook carries exact totals.
  • Leads and signups: on Tracking, use Set what a win is worth on each goal (or on Form conversions: lead, signup, subscribe). Not selling directly? Estimate from close rate: if about one in ten signups becomes a $500 customer, a signup is worth roughly $50. Reports label that revenue as estimated. You can change or clear an estimate anytime.
  • Real amounts win: if the same conversion name arrives with a value from track, a webhook, or an order-grade page total, that number is used and the Tracking estimate is ignored for that event. Estimates only fill in when the event carries no value. Different names stay independent (purchase does not use a signup estimate).
Values apply to new conversions only. Changing an estimate does not rewrite history.

The tag API

Once the snippet is installed, every page has a global waverunner() function with three commands:

// Record a conversion. Value is in dollars; the optional orderId
// makes the same purchase count once even if it is reported twice
// (for example by this call and your store's webhook).
waverunner("track", "purchase", { value: 129.99, orderId: "1001" });

// Tell us who the visitor is when you learn it (sign-in, checkout).
// This links the browser to that email, so conversions your backend
// sends later still connect to the ad that brought them, even from
// another device. Emails are stored only as salted one-way hashes.
waverunner("identify", "customer@example.com");

// Wire in your cookie banner: declined visitors get the same
// do-not-share treatment as Global Privacy Control.
waverunner("consent", { adSharing: userAcceptedAdCookies });
  • track accepts any conversion name you choose, plus optional value, currency, and orderId.
  • identify takes an email string, or an object with email, phone, firstName, and lastName. It is the glue between browser visits and server-side webhook conversions: without it, a backend-reported sale can only match through the same browser.
  • consentstores the visitor's choice for a year. Measurement for your own reports continues either way; declining stops all sharing with ad platforms.

How attribution works

  • Last-touch: a conversion is credited to the most recent qualifying touch. That stamp drives billed results, wallet charges, and ROAS. All touches are still stored.
  • Clicks beat views: ad clicks carry a first-party click ID (30-day window) and always win over view-through exposure.
  • View-through: TV and web display impressions are recorded by a first-party pixel; the view-through window is configurable at 7, 14, or 30 days.
  • Assisted conversions: on a campaign's Performance tab, assists show when another channel touched someone earlier (click, household view, or person-resolved view) before a different channel got last-touch credit. Assists are reporting-only and never change wallet charges or ROAS. Details: Assisted conversions and Lift.
  • Closed loop: attributed conversions are forwarded to Meta (Conversions API) and Google (offline conversion uploads), so the channels’ own optimizers learn from your results.

Cookies the tag sets

All cookies are first-party, set on your own domain:

CookiePurposeLifetime
_wr_vidVisitor ID: recognizes a returning browser365 days
_wr_sidSession ID: groups a visit30 minutes, sliding
_wr_cidClick ID: links a visit to the ad click that caused it30 days
_wr_aidAd ID: which specific ad drove the click30 days
_wr_utmFirst-touch UTM parametersSession
Emails and IP addresses are hashed with a salt before storage; Waverunner never stores raw personal identifiers from your visitors. See the privacy policy for the full data-handling picture.