Form Attribution is a lightweight script that automatically captures and adds marketing attribution data to your forms as hidden fields.

Quick Start

Add the script to your website before the closing </body> tag:

<script src="https://cdn.jsdelivr.net/npm/form-attribution@latest/dist/script.min.js"></script>

That's it! The script will automatically:

  1. Capture common URL parameters and metadata (e.g. landing page)
  2. Store the data in the user's browser temporarily
  3. Inject hidden fields into all forms on the page

Data Attributes

Configure the script by adding optional data attributes to the script tag:

<script src="/dist/script.min.js"
  data-storage="localStorage"
  data-field-prefix="attr_"
  data-extra-params="gclid,fbclid"
  data-exclude-forms=".no-track"
  data-debug="true">
</script>
Attribute Default Description
data-storage sessionStorage Storage method: sessionStorage, localStorage, or cookie
data-field-prefix "" Prefix for hidden field names (e.g., attr_ creates attr_utm_source)
data-extra-params "" Comma-separated list of additional URL parameters to capture
data-exclude-forms "" CSS selector for forms to exclude from injection
data-storage-key form_attribution_data Custom key name for stored data
data-debug false Enable console logging and debug panel
data-privacy true Set to "false"to disable GPC/DNT privacy signal detection
data-click-ids false Set to "true"to automatically capture ad platform click IDs

Storage Options

Choose where attribution data is persisted between page loads:

Session Storage (default)

Data persists for the browser session only.

<script src="/dist/script.min.js" data-storage="sessionStorage"></script>

Local Storage

Data persists until explicitly cleared.

<script src="/dist/script.min.js" data-storage="localStorage"></script>

Cookies

Data accessible server-side and can span subdomains.

<script src="/dist/script.min.js" data-storage="cookie"></script>

Cookie Settings

When using data-storage="cookie", additional options are available:

Attribute Default Description
data-cookie-domain "" Cookie domain (e.g., .example.com)
data-cookie-path / Cookie path
data-cookie-expires 30 Expiration in days
data-cookie-samesite lax SameSite policy: lax, strict, or none

Example: Cross-Subdomain Tracking

<script src="/dist/script.min.js"
  data-storage="cookie"
  data-cookie-domain=".example.com"
  data-cookie-expires="90">
</script>

Privacy Controls

By default, the script respects user privacy preferences:

  • Global Privacy Control (GPC): Disables tracking when navigator.globalPrivacyControl  is true
  • Do Not Track (DNT): Disables tracking when DNT is enabled

When privacy signals are detected, no data is captured or stored.

Disable Privacy Signal Detection

If you need to disable privacy signal detection (not recommended):

<script src="/dist/script.min.js" data-privacy="false"></script>
Warning: Disabling privacy signals may violate user expectations and applicable privacy regulations.

Click ID Tracking

Enable automatic capture of ad platform click IDs:

<script src="/dist/script.min.js" data-click-ids="true"></script>

When enabled, the following parameters are automatically tracked:

Parameter Platform
gclid Google Ads
fbclid Meta Ads
msclkid Microsoft Advertising
ttclid TikTok Ads
li_fat_id LinkedIn Ads
twclid Twitter/X Ads

Debug Panel

The debug panel provides a visual interface for inspecting attribution data, viewing tracked forms, and monitoring activity in real-time.

Enabling the Debug Panel

Add data-debug="true"to the script tag:

<script src="/dist/script.min.js" data-debug="true"></script>

Features

  • Data Tab: View all captured UTM parameters and metadata
  • Forms Tab: See all forms on the page and their injection status (click to highlight)
  • Log Tab: Real-time activity log with timestamps
  • Copy: Export attribution data as JSON to clipboard
  • Clear: Remove all stored attribution data
  • Refresh: Re-inject data into all forms

The panel can be minimized, dragged to reposition, and its state persists across page reloads.

Note: The debug panel is intended for development only. Remove data-debugbefore deploying to production.

JavaScript API

Form Attribution exposes a global FormAttribution object for programmatic access to attribution data and control.

Methods

Method Returns Description
getData() Object|null Get all captured attribution data
getParam(name) string|null Get a specific parameter value
getForms() Array Get list of tracked forms with their status
clear() void Clear all stored attribution data
refresh() void Re-inject data into all forms
on(event, callback) Object Register a callback for events (chainable, supports multiple listeners)
off(event, callback) Object Unregister a previously registered callback (chainable)

Properties

Property Type Description
config Object Current configuration (read-only)
github string GitHub repository URL
docs string Documentation URL

Events

Event Payload Description
onReady { data, config } Fired when initialization is complete
onCapture { data } Fired when new data is captured
onUpdate { data } Fired when data is updated

Example Usage

// Wait for initialization
FormAttribution.on('onReady', ({ data, config }) => {
  console.log('Attribution ready:', data);
});

// Get all attribution data
const data = FormAttribution.getData();
console.log(data);
// { utm_source: 'google', utm_medium: 'cpc', ... }

// Get a specific parameter
const source = FormAttribution.getParam('utm_source');
console.log(source); // 'google'

// Get tracked forms
const forms = FormAttribution.getForms();
forms.forEach(form => {
  // Status: 'Injected' (has data), 'Ready' (no data yet), or 'Excluded'
  const status = form.excluded ? 'excluded' : form.injected ? 'injected' : 'ready';
  console.log(form.name, status);
});

// Clear data (useful for testing)
FormAttribution.clear();

// Re-inject into forms
FormAttribution.refresh();

// Access current config
console.log(FormAttribution.config.storage); // 'sessionStorage'

// Remove a callback
const myHandler = ({ data }) => console.log('Captured:', data);
FormAttribution.on('onCapture', myHandler);
// Later...
FormAttribution.off('onCapture', myHandler);

Captured Parameters

URL Parameters (default)

Parameter Description
utm_source Traffic source (e.g., google, newsletter)
utm_medium Marketing medium (e.g., cpc, email)
utm_campaign Campaign name
utm_term Paid search keywords
utm_content Content variant for A/B testing
utm_id Campaign ID
ref Referrer tracking parameter

Metadata (automatically captured)

Parameter Description
landing_page First page URL visited
current_page Current page URL (where form was submitted)
referrer_url Document referrer
first_touch_timestamp ISO 8601 timestamp of first visit

Injected Fields

Hidden fields are injected with the following attributes:

<input type="hidden"
  name="utm_source"
  value="google"
  data-form-attribution="true"
  data-form-attribution-managed="true">
  • Existing hidden fields with matching names are updated (no duplicates created)
  • User-visible form fields are never modified
  • All values are HTML-entity encoded for XSS protection

Storage Fallbacks

The script uses intelligent fallbacks when a storage type isn't available:

Requested Fallback Chain
localStorage localStorage → sessionStorage → cookie → memory
sessionStorage sessionStorage → cookie → memory
cookie cookie → memory
Navigation