@velocityio/web-attribution-sdk
v0.1.0
Published
Velocity attribution & conversion tracking SDK
Readme
Velocity Web Attribution SDK
Velocity's attribution & conversion tracking SDK for advertisers. Report conversion events (Purchase, Lead, AddToCart, or custom events) back to Velocity, tied to the ad click that drove the visit.
- Full documentation: https://docs.velocity.io/web/attribution
- API reference: https://docs.velocity.io/web/attribution/api-reference
Backend status: not yet live. The conversion ingestion endpoints (browser and S2S) are specifications the backend has not implemented yet — events sent today will not be recorded.
Installation
npm install @velocityio/web-attribution-sdkQuick Start
import { VelocityAttribution, StandardEvents } from '@velocityio/web-attribution-sdk';
const attribution = new VelocityAttribution({ advertiserKey: 'YOUR_ADVERTISER_KEY' });
attribution.setConsent(true); // required — nothing is sent until consent is granted
attribution.track(StandardEvents.Purchase, {
eventId: 'ORD-123', // dedup key, shared with any server-side postback
value: 49.99,
currency: 'USD'
});API Reference
| Method | Description |
|--------|-------------|
| new VelocityAttribution({ advertiserKey, cookieDomain?, disableCookies?, timeout?, logger? }) | advertiserKey is required — usually the only field you need. cookieDomain overrides the auto-detected eTLD+1; disableCookies forces localStorage-only. Both are escape hatches for unusual deployments. |
| setConsent(granted) | GDPR consent. true unblocks sending and attribution storage; false stops sending and clears the stored click ID and browser ID. |
| setDoNotSell(optOut) | CCPA "Do Not Sell" flag, transmitted on every event as privacy.do_not_sell. |
| track(eventName, params?, useBeacon?) | params accepts { eventId, value, currency, orderId, contents, custom }. Pass useBeacon = true from a page-unload handler so delivery uses navigator.sendBeacon instead of fetch. Events tracked while consent is still pending are buffered (up to 20) and sent once consent is granted. |
| destroy() | Releases listeners and buffered events. Call on SPA component unmount or before creating a replacement instance; not needed on standard multi-page sites. |
Standard Events
PageView, ViewContent, Search, AddToCart, InitiateCheckout, AddPaymentInfo, Purchase, Lead, CompleteRegistration, StartTrial, Subscribe, Contact — exported as StandardEvents. Custom names are also accepted.
Purchase events should include value and currency (a debug warning is logged when missing).
Event Deduplication (eventId)
Every event carries an event_id. Supply your own via params.eventId when the same event may also arrive from your server — Velocity deduplicates on (advertiser key, event name, event id). For Purchase, your order ID is a good choice. Auto-generated UUID when omitted.
Server-to-Server (S2S) Events
Your backend can also report conversions directly over HTTPS — no SDK needed. Send batched events to the documented endpoint with Authorization: Bearer <apiSecret> (a server-side secret issued per account), using the same event schema and the same event_id for browser/server deduplication. See the S2S Conversions API spec for the full contract, including how to forward the first-party _vlc/_vlp cookies for attribution.
How Click Attribution Works (click_id)
- A user clicks a Velocity ad. Velocity's click redirect appends a
click_idquery parameter to your landing page URL (e.g.https://shop.example.com/?click_id=abc123). This requires the campaign to be served through Velocity's redirect — without it there is noclick_idand conversions arrive unattributed. - On page load the module captures
click_idfrom the URL and — once tracking consent is established — persists it as a first-party cookie (_vlc, 90 days) on your registrable domain (eTLD+1), withlocalStorageas a same-origin fallback. A freshclick_idalways overwrites a stored one (last click wins). - Later funnel pages with no
click_idin the URL fall back to the stored value — the cookie scope means attribution survives cross-subdomain funnels (shop.example.com→checkout.example.com) as well as multi-page checkouts. It does not carry across a different registrable domain. - Every
track()call attaches whichever click ID is current; conversions without one are still sent, just unattributed.
The module also maintains a first-party browser ID (_vlp cookie, ~13 months, plus a localStorage mirror) — a random UUID attached to every event as a secondary match signal, created only once consent permits and cleared on denial.
Both IDs are self-healing: they are held in memory for the page lifetime and re-persisted on every track() call and on tab-hide, so third-party scripts wiping cookies/localStorage mid-session cannot permanently remove them (consent denial always wins over healing).
Consent & Privacy
The SDK supports GDPR and CCPA compliance with automatic CMP detection and explicit consent APIs.
Automatic CMP Detection
The SDK automatically reads consent signals from any IAB TCF v2 compatible CMP (OneTrust, Didomi, etc.) via the standard __tcfapi interface. No configuration needed — if a CMP is present on the page, the SDK reads its consent data.
Explicit Consent API
// Set consent at construction time
const attribution = new VelocityAttribution({
advertiserKey: 'YOUR_KEY'
});
// Or set consent dynamically
attribution.setConsent(true); // GDPR consent granted
attribution.setConsent(false); // GDPR consent revoked
attribution.setDoNotSell(true); // CCPA opt-outHow It Works
track() is gated client-side: while consent is unknown or denied, calls are no-ops and no request leaves the browser. A detected IAB TCF v2 CMP is read automatically (TCF Purpose 1), the same as the main SDK. Explicitly denying consent also clears all stored attribution IDs. The consent state is transmitted on every event as consent.ad_storage (granted / denied / unknown) plus the raw TCF string when a CMP is present.
Page Unload Tracking
window.addEventListener('pagehide', () => {
attribution.track('Lead', { eventId: 'ORD-123' }, true); // sendBeacon
});The third parameter (useBeacon = true) ensures delivery uses navigator.sendBeacon instead of fetch, which guarantees events send even as the page unloads.
Cleanup & Lifecycle
Call destroy() when the SDK instance is no longer needed to release all internal resources:
attribution.destroy();This releases listeners and buffered events. After calling destroy(), the instance cannot be reused — create a new VelocityAttribution instance if needed.
When to call destroy():
- SPA route transitions where the SDK is no longer needed
- Component unmount in frameworks like React/Vue/Angular
- Before creating a new SDK instance with different configuration
When you don't need destroy():
- Standard multi-page sites (page unload cleans up automatically)
- Single SDK instance that lives for the entire page session
CDN & Google Tag Manager
Direct-install (CDN script snippet) and Google Tag Manager integrations are also available. See the attribution documentation for:
- CDN installation instructions
- GTM template configuration
- Advanced consent management
- Event schema reference
- Troubleshooting guide
Documentation
For the complete integration guide, visit the Velocity attribution documentation.
License
MIT
