Handoff attribution setup for website maintainers
For website maintainers: handoff tracking is optional and off by default. Install the receiver for your chosen existing browser KPI before setting track_handoffs:true on an HTTPS first-party handoff action. Do not enable it for third-party destinations or execute actions.
Start with page-local browser properties and no new persistence, backend code or database migration on your site. Vendor the provider-neutral receiver module shown below into your app. It has no side effects on import. Call it only when the relevant analytics collection is permitted. Cross-page/session storage is an optional extension: supply consent-aware session storage explicitly; clearHandoff on logout, identity changes and consent withdrawal. Without storage it reads only the current URL. Codes expire 30 days after issuance; local retention is bounded to 30 days from first observation.
Attach lazyweb_handoff_code to the landing event and each selected real KPI event. Backend signup/payment attribution is a separate optional extension, not a browser installation prerequisite. Carry the code into the server session or checkout intent and then the verified outcome event; a browser snippet alone cannot attach it to webhooks. Use your existing analytics provider and event names rather than creating a duplicate conversion.
Resolve codes privately through the authenticated owner POST /api/sites/:id/attribution/resolve with {code,event_time}; use the provider event timestamp for historical imports. Resolution returns only the source operation and link metadata. A code associates a link with an operation, not proof of a person, a completed conversion or causation. Never use it as authentication or put private context in the URL.
The Labs tracked-link activity panel reads code-bearing PostHog events independently of the selected KPIs. It counts links issued during the displayed range in the website’s reporting timezone, verified $pageview arrivals, and the copy event configured in the handoff action’s optional handoff_copy_event field (install intent, not completed installations). Set this field to the site’s real event name, for example mcp_install_prompt_copied; leave it unset when copy instrumentation is unknown, so missing instrumentation is not reported as zero. The same link may produce multiple pageviews or copies; these are event occurrences, not unique people. It requires an active PostHog connection, but no KPI slot or attribution-import selection. Unsupported or unavailable provider counts remain missing; reads are cached for up to five minutes. New tracked links may be disabled without removing historical outcomes.
For PostHog, open Manage KPIs and enable Import agent attribution after outcome properties are wired. The Labs chart can compare all events with agent-associated events and show separate validated handoff, AI referrer and AI-tagged campaign counts. Existing GA4/Plausible integrations import totals only; their attribution import is not yet supported.
Before enabling, verify the receiver and downstream property propagation with local fixtures or the provider’s test environment. Do not create production QA purchases or customer events. Issuing a URL or fetching it is not a conversion. Preserve unrelated traffic and existing consent/identity behavior.
// Vendor/bundle the module from https://app.thelazyweb.com/handoff-attribution.js
import {handoffProperties,clearHandoff} from './handoff-attribution.js';
// Inside your existing consent-approved analytics path:
let properties=handoffProperties({url:window.location.href});
// Keep only in this document, consume lw_ref using your router even if denied.
// Merge properties into existing permitted landing and same-page KPI captures.
// Clear page-local properties on logout, identity change or consent withdrawal:
// properties={}; Reconsent must not replay the old arrival.
// For server outcomes, pass the code through your server session/checkout intent.
// Optional cross-page persistence: pass consent-aware storage to handoffProperties.
// If using it, clearHandoff(window.sessionStorage) on the same lifecycle events;
// preserve the original observation time instead of renewing it on each event.