PruuvDocs

Pixel SDK

The Pruuv Pixel is a lightweight JavaScript snippet (~4 KB) that you add to your landing pages. It automatically captures UTM parameters and ad platform click IDs on page load, then sends a conversion event to Pruuv when you call Pruuv.track().

Both steps are required. The pixel captures click IDs automatically on page load and stores them in first-party cookies. Pruuv.track() is what actually delivers those click IDs to Pruuv so matched conversions can be sent back to your ad platforms. Without track(), Pruuv has no data to send.

Quick start

1. Add the snippet to your landing page

Paste the following before the closing </body> tag on every landing page where you want to track conversions:

html
<script>
  window.PruuvConfig = {
    stageId: 'YOUR_STAGE_ID',
    token:   'YOUR_WEBHOOK_TOKEN'
  };
</script>
<script src="https://app.pruuv.io/pixel.min.js" async></script>

Replace YOUR_STAGE_ID and YOUR_WEBHOOK_TOKEN with the values from Connections > Conversion & CRM Data > Funnel Webhooks in your Pruuv dashboard.

2. (Optional) Identify the visitor

Call Pruuv.identify() when you know who the visitor is — for example, when they submit a form step or log in. This stores their identity in a first-party cookie so subsequent track() calls don't need to repeat it. The userId becomes the reference field in the funnel event, enabling cross-session identity stitching.

javascript
// Call when you know who the user is (form step, login, etc.)
Pruuv.identify('crm-contact-id', {
  email:   'jane@example.com',
  phone:   '+441234567890',
  name:    'Jane Smith',
  company: 'Acme Ltd'
});

// Then track() with no identity fields needed — they're stored
Pruuv.track('Lead', {
  value:    250,
  currency: 'GBP'
});

3. Fire a conversion event

Call Pruuv.track() at the moment a lead or sale is confirmed — for example, after a form is successfully submitted. If you called identify() earlier, email and phone are already stored and will be sent automatically.

javascript
Pruuv.track('Lead', {
  email:    'jane@example.com',   // hashed in browser — or omit if identify() was called
  phone:    '+441234567890',      // hashed in browser — or omit if identify() was called
  value:    250,                  // revenue value
  currency: 'GBP',               // ISO 4217 currency code
  order_id: 'CRM-REF-001'        // your internal reference (overrides identify userId)
});

All fields are optional except the event name. The pixel handles everything else automatically.

Full API reference

Pruuv.identify(userId, traits)

ParameterTypeDescription
userIdstring (required)Your internal contact or lead ID — becomes the reference field in the funnel event. Use your CRM contact ID, email, or any stable identifier.
traits.emailstringEmail address. Hashed with SHA-256 before sending.
traits.phonestringPhone number in E.164 format. Hashed before sending.
traits.namestringDisplay name (not sent in the webhook — for local reference only).
traits.companystringCompany name (not sent in the webhook — for local reference only).

Identity is stored in a 90-day first-party cookie and localStorage. It persists across page loads untilPruuv.reset() is called.

Calling identify() multiple times is safe — the most recent call wins. If the same visitor calls identify() with different userIds across sessions (e.g. after switching accounts), each event is stored independently.

Pruuv.track(eventName, options)

ParameterTypeDescription
eventNamestring (required)Arbitrary event name — e.g. 'Lead', 'Appointment', 'Sale'. Stored in the funnel event for filtering.
options.emailstringOverrides stored identity email for this call. Hashed before sending.
options.phonestringOverrides stored identity phone for this call. Hashed before sending.
options.valuenumberRevenue or conversion value.
options.currencystringISO 4217 currency code (e.g. GBP, USD, EUR).
options.order_idstringYour order or CRM reference. Overrides identity userId as the event reference.
options.referencestringExplicit event reference. Takes priority over order_id and identity userId.

Reference resolution order: options.referenceoptions.order_ididentity.userIdpruuv_{timestamp}

Pruuv.reset()

Clears the stored identity. Call this on logout so subsequent events are not associated with the previous user. Does not clear click ID cookies — those persist for attribution purposes.

First-touch vs last-touch attribution

The Pruuv Pixel automatically maintains two attribution signals:

SignalCookieBehaviour
Last touch_pruuv_sessionUpdated on every visit where click IDs or UTMs are present. Sent as the primary attribution in every track() call.
First touch_pruuv_first_touchWritten once on the visitor's very first tracked visit. Never overwritten. Sent as first_touch alongside last-touch when the two differ.

When a visitor clicks a Google ad, then later clicks a Meta ad and converts, Pruuv records both: the Meta click as last-touch (used for conversion sending) and the Google click as first-touch (surfaced in agent analysis and cross-channel reporting). Both signals are stored in the funnel event automatically — no extra code required.

Native attribution (pruuv_aid)

Pruuv's native attribution path lets you track conversions back to a specific ad creative without relying on platform click IDs. Instead of waiting for a gclid or ttclid in the URL, you embed a Pruuv-generated ID (pruuv_aid) directly in your ad's destination URL template. The pixel captures it automatically on landing.

This approach is platform-agnostic — it works with any ad network that supports URL parameters, and does not depend on the ad platform's click ID system. It is particularly useful when click IDs are stripped by ad blockers or browser privacy settings.

Setup: add pruuv_aid to your ad URL template

In your ad platform's URL template field, add pruuv_aidas a custom parameter. Use the ad's own dynamic substitution macro to fill it per creative. Here are examples for each platform:

PlatformURL template parameter
Meta Ads?pruuv_aid={{ad.id}}
Google Ads?pruuv_aid={creative}
TikTok Ads?pruuv_aid=__ADID__
Any platform?pruuv_aid=YOUR_STATIC_AD_ID

The value can be a platform macro (so each ad gets its own ID automatically) or a static string you define per campaign. The pixel reads whatever value is in the URL parameter — it does not validate the format.

How it works

On page load, the pixel reads the pruuv_aid URL parameter and stores it in the session cookie alongside other click IDs. When Pruuv.track() is called, the pruuv_aid is included in the webhook payload. Pruuv then matches the event to the specific ad in the pruuv_native_ads table, enabling attribution to that creative, ad set, and campaign — fully server-side, no pixel ID required.

Platform click IDs take precedence for conversion sending. If both a pruuv_aid and a gclid / ttclid are present, the platform click ID is used for conversion sending (Google Upload / TikTok Events API) while pruuv_aid is used for creative-level attribution reporting. You do not need to choose — the pixel captures both.

Manual override in track()

If you need to pass a pruuv_aid that was not in the URL (e.g. stored in your own session state), you can pass it directly in track():

javascript
Pruuv.track('Lead', {
  pruuv_aid: 'your-ad-id-here',
  email:     'jane@example.com',
  value:     250,
  currency:  'GBP'
});

An explicit pruuv_aid passed to track() overrides any value captured automatically from the URL.

How it works

On every page load

The pixel runs silently as soon as the page loads. It reads the following URL parameters and stores them in first-party cookies (90-day expiry):

ParameterPlatformCookie
utm_source, utm_medium, utm_campaign, utm_content, utm_termAll_pruuv_session
gclid, wbraid, gbraidGoogle Ads_pruuv_session
ttclidTikTok Ads_pruuv_session
msclkidMicrosoft Ads_pruuv_session
fbclidMeta Ads_fbc

Two special cookies are also maintained:

  • _pruuv_first_touch — a snapshot of the very first click that brought this visitor. Written once and never overwritten.
  • _fbp — Meta's browser ID. Generated on first visit and persists for 90 days. Required for Meta Conversions API matching.

On Pruuv.track()

When you call track(), the pixel:

  1. Reads stored click IDs and UTMs from cookies (last-touch)
  2. Reads stored identity from _pruuv_identity — merges with any values you pass explicitly
  3. SHA-256 hashes email and phone in the browser — PII never leaves in plaintext
  4. If the visitor's first-touch differs from their current session, includes it as first_touch in the payload
  5. Sends a single POST to your Pruuv webhook with all signals included

Framework examples

React / Next.js

jsx
async function handleSubmit(data) {
  const result = await submitForm(data)
  if (result.ok) {
    window.Pruuv?.track('Lead', {
      email:    data.email,
      value:    250,
      currency: 'GBP',
      order_id: result.referenceId
    })
  }
}

The optional chaining (?.) means the call is a no-op if the pixel is not loaded.

HTML form

html
<form id="contact-form">
  <!-- your fields -->
  <button type="submit">Get a quote</button>
</form>

<script>
  document.getElementById('contact-form').addEventListener('submit', function(e) {
    e.preventDefault();
    var email = this.querySelector('[name="email"]').value;

    // submit your form here, then on success:
    Pruuv.track('Lead', { email: email, currency: 'GBP' });
  });
</script>

Google Tag Manager

Create a Custom HTML tag triggered on your form success event or thank-you page:

html
<script>
  Pruuv.track('Lead', {
    email:    '{{DLV - email}}',
    value:    {{DLV - lead_value}},
    currency: 'GBP',
    order_id: '{{DLV - reference}}'
  });
</script>

Privacy

  • Email and phone are hashed with SHA-256 in the browser before being sent — Pruuv never stores plaintext PII
  • The pixel sets first-party cookies only — no third-party cookies, no cross-site tracking
  • No data is sent to any third party by the pixel — all data goes directly to your Pruuv webhook endpoint
  • The pixel does not load any external scripts or resources

Troubleshooting

No events appearing in Pruuv

  • Check the browser network tab — look for a POST to /api/webhooks/funnel/... and inspect the response
  • Verify window.PruuvConfig.stageId and window.PruuvConfig.token are set before the pixel loads
  • Confirm the token matches the one shown in Connections > Funnel Webhooks

Events appear but click IDs are missing

  • Ensure the pixel snippet is on the landing page — the page the user arrives on after clicking the ad — not just the thank-you page
  • Click IDs are only available in the URL on the initial landing. They cannot be recovered if the user navigates before the pixel loads

Meta conversion matching rate is low

  • Ensure fbc and fbp are being captured — they are only available via the browser pixel
  • Include email or phone in Pruuv.track() for additional matching signals
  • Server-side-only integrations will always have lower Meta match rates without the fbc/fbp cookies