Attribution snippet

One site-wide script that records where each visitor came from and fills your forms' hidden fields automatically.

The attribution snippet is the foundation of everything else. Installed once, site-wide, it:

  • Records the first touch. On a visitor’s first page view it captures the UTM parameters, Google click ID (gclid), referrer and landing page, works out the marketing channel, and stores the result in a cookie (kq_attr, 30 days). Return visits keep the original — attribution is first-touch.
  • Fills your forms’ hidden fields. On every page it writes the stored values into hidden form inputs (see Form webhook for the field list), so every submission carries its own attribution.
  • Sends a beacon fallback. When a visitor shows form intent (focuses a field, or a form scrolls into view), it sends the attribution data to your instance so calls and emails can be matched by IP and browser later, even without a form submission. Throttled to once per 30 minutes per session.
  • Powers the email enquiry link. The mailto snippet reads the same cookie to inject the page URL and click ID into the enquiry email body.

Your personalised copy of the snippet — with your instance’s beacon URL already baked in — is in the app under Settings → Setup Guide → section 1. The Setup Guide also has a live checker that verifies the snippet is installed and beaconing correctly on your site.

Installing it

Paste the snippet just before the closing </body> tag on every page of your site. In most CMSs that means the site-wide footer template or a “custom scripts” box. If your site runs WordPress, there is also a small plugin version of the snippet — ask your Syft admin.

That’s the whole install. The snippet has no visible output and doesn’t slow the page — it’s a few kilobytes of plain JavaScript with no dependencies.

How the channel is worked out

The snippet classifies each first visit into a channel, in this priority order:

Signal on first visitChannelDrill-down
gclid presentPaid SearchGoogle
utm_medium is cpc / ppc / paid_searchPaid Search (or Paid Social if the source is a social network)Source engine/network
utm_medium is paid_socialPaid SocialNetwork
UTM source/medium = emailEmailSource
Other UTMs from a social networkOrganic SocialNetwork
Other UTMsReferralSource
No UTMs, referrer is a search engineOrganic SearchEngine
No UTMs, referrer is a social networkOrganic SocialNetwork
No UTMs, other referrerReferralReferrer host
NothingDirect

Campaign lands in drill-down 2 and ad content / keyword in drill-down 3. The snippet also generates a unique transaction_id per visitor, used by the Google Ads value-restatement integration.

How the snippet finds your form fields

You don’t wire anything up manually — add hidden fields to your form and the snippet finds them, matching in three ways (in order):

  1. By field namename="channel", name="gclid", etc.
  2. By CSS classclass="kq-attr-channel" — for form builders that don’t let you set the input name directly (e.g. Gravity Forms).
  3. By data attributedata-kq-attr="channel".

Two extras for compatibility:

  • Standard UTM names work too. Fields named utm_source, utm_medium, utm_campaign, utm_term, utm_content are filled with the corresponding channel values.
  • Attributer-style placeholders work. An input whose default value is [channel] (or any other known key in square brackets) gets replaced. This makes Syft a drop-in replacement for Attributer.io — existing forms keep working without changes.

Forms added to the page after load (modals, lazy-loaded blocks) are caught automatically.

The snippet

For reference, this is what the snippet does — but don’t copy it from here. Use the pre-filled version from your Setup Guide, which has your instance’s beacon URL in place of https://YOUR-INSTANCE/api/attribution.

<script>
(function () {
  var COOKIE = 'kq_attr', DAYS = 30;
  var BEACON_URL = 'https://YOUR-INSTANCE/api/attribution';
  // 1. On first visit: read UTMs, gclid, referrer + landing page,
  //    classify the channel, store everything in the kq_attr cookie.
  // 2. On every page: fill hidden form fields (by name, kq-attr-* class,
  //    data-kq-attr attribute, or [placeholder] value) with the stored data.
  // 3. On form intent: beacon the data to your instance as a fallback
  //    matching path for calls and emails (30-minute session throttle).
  /* full implementation supplied by your Setup Guide */
})();
</script>

Checking it works

In the app, Setup Guide → section 1 has a snippet checker: give it a page URL on your site and it reports whether the page is reachable, whether the kq_attr cookie gets set, whether the beacon fires to the right URL, and whether recent beacons have been received. Use it after install and after any site redesign.