Skip to main content

Snippet Setup

This page is the HTML / plain-script installation guide for the Selgeo tracking snippet (selgeo.js) — a lightweight JavaScript file that runs on your website, registers partner referral clicks, and stores attribution data in the visitor's browser for later conversion matching. Use this guide if you control your site's raw HTML directly (static sites, Webflow, Shopify Liquid, custom server-rendered pages, or a tag manager).

Using a framework?
  • Next.js — see the Next.js guide for the next/script component pattern.
  • React (Vite) — see the React (Vite) guide for index.html placement and the useEffect fallback.
  • WordPress — see the WordPress guide for Site Editor, footer.php, and header-footer-plugin placement.

API Version: v1

Basic installation

Add the following <script> tag to every page of your website, just before the closing </body> tag:

<script
async
src="https://cdn.selgeo.com/v1/selgeo.js"
data-merchant="pk_test_YOUR_KEY"
></script>

Replace pk_test_YOUR_KEY with your public API key from the Selgeo dashboard (Settings > API Keys).

Required attributes

AttributeDescription
srcCDN URL for the snippet. Always use https://cdn.selgeo.com/v1/selgeo.js.
data-merchantYour public API key (pk_test_* for test mode, pk_live_* for live mode).
asyncLoad the snippet asynchronously so it does not block page rendering.

Optional attributes

AttributeDescription
data-debugEnable debug logging in the browser console. Remove before going live.
data-api-urlOverride the API endpoint URL. For advanced use only (e.g., custom proxy).

How it works

When a visitor arrives at your site with a ?ref= parameter in the URL (e.g., https://your-site.com/pricing?ref=abc123), the snippet:

  1. Detects the ref query parameter.
  2. Registers the click with the Selgeo API using your public key.
  3. Stores the click_id returned by the API in the browser's sessionStorage.
  4. Removes ?ref= from the URL using history.replaceState to keep URLs clean.
  5. Rewrites Stripe Payment Links on the page to include client_reference_id=CLICK_ID.

If there is no ?ref= parameter, the snippet does nothing. It has zero overhead on pages where no referral is taking place.

Storage mechanism

The snippet stores attribution data in sessionStorage, not cookies:

KeyValueLifetime
__selgeo_cidThe click_id (UUID)Until the browser tab closes
__selgeo_vtkA visitor token (UUID)Until the browser tab closes

Privacy implications:

  • sessionStorage is tab-scoped -- it is not shared across tabs or windows.
  • Data is automatically cleared when the tab is closed.
  • No cookies are set. No cookie consent banner is required for Selgeo tracking.
  • The snippet sends no data to Selgeo unless a ?ref= parameter is present.

Reading the click ID

Your frontend code can read the stored click_id at any time:

const clickId = __selgeo.getClickId();
// Returns a UUID string (e.g., "f47ac10b-58cc-4372-a567-0e02b2c3d479")
// Returns null if no referral click was recorded in this session

This is useful when you need to pass the click_id to your backend -- for example, when creating a Stripe Checkout Session or calling the Conversion API.

Available methods

MethodReturnsDescription
__selgeo.getClickId()string | nullThe current click ID, or null if none exists
__selgeo.getVisitorToken()string | nullThe current visitor token, or null
__selgeo.checkUrl()voidManually re-check the current URL for a ?ref= parameter

Single-page applications (SPAs)

The snippet automatically monitors URL changes in single-page applications. It listens for:

  • popstate events (browser back/forward navigation)
  • history.pushState and history.replaceState calls (programmatic navigation)

When the URL changes and contains a new ?ref= parameter, the snippet captures the click automatically. No additional configuration is needed for React, Vue, Angular, or other SPA frameworks.

If you dynamically construct URLs with ?ref= parameters and navigate programmatically, the snippet will detect the change automatically.

Manual URL check

In rare cases where the automatic detection does not trigger (e.g., the ?ref= parameter is added after page load via JavaScript without using history.pushState), you can manually tell the snippet to re-check:

__selgeo.checkUrl();

If your page contains links to Stripe Payment Links (https://buy.stripe.com/...), the snippet automatically appends ?client_reference_id=CLICK_ID to them when a referral click is active.

<!-- Before snippet runs -->
<a href="https://buy.stripe.com/test_abc123">Subscribe</a>

<!-- After snippet runs (when a click_id is stored) -->
<a href="https://buy.stripe.com/test_abc123?client_reference_id=CLICK_ID">Subscribe</a>

The snippet also watches for dynamically added Payment Links (via MutationObserver) and rewrites them as they appear. This works with SPAs and lazily loaded content.

Merchant override protection: If you set client_reference_id on a Payment Link yourself, the snippet will not overwrite your value. Your explicit value always takes priority.

For a detailed walkthrough, see Stripe Payment Links.

Tag manager installation

If you use Google Tag Manager (GTM) or another tag manager, add the snippet as a custom HTML tag:

  1. Create a new Custom HTML tag in GTM.
  2. Paste the script tag:
    <script
    async
    src="https://cdn.selgeo.com/v1/selgeo.js"
    data-merchant="pk_test_YOUR_KEY"
    ></script>
  3. Set the trigger to All Pages.
  4. Publish the container.
Tag manager timing

When using a tag manager, the snippet may load slightly later than a direct <script> tag. This is fine for most use cases, but if you need the click_id available immediately on page load (e.g., to pass it to a server-rendered checkout form), add the snippet directly to your HTML instead.

Placement recommendations

ScenarioRecommendation
Standard websiteAdd to every page via global layout/template
SPA (React, Vue, etc.)Add to index.html once -- snippet handles route changes
Landing pages onlyAdd only to pages where partner traffic lands
Checkout page onlyNot recommended -- the snippet must be on the landing page to capture the ?ref= parameter
The snippet must be on the landing page

The ?ref= parameter is present only in the initial URL when the visitor clicks a partner link. If the snippet is not loaded on that page, the click will not be recorded and the click_id will not be available for later conversion attribution.

Verify your installation

  1. Add data-debug to the script tag temporarily.
  2. Visit your site with a test tracking link: https://your-site.com/?ref=YOUR_TEST_REF
  3. Open Developer Tools (F12) and check the Console for:
    [selgeo] ref detected YOUR_TEST_REF
    [selgeo] click_id stored xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  4. Check sessionStorage in the Application tab (Chrome) or Storage tab (Firefox):
    • __selgeo_cid should contain a UUID
    • __selgeo_vtk should contain a UUID
  5. Call the API in the console:
    __selgeo.getClickId() // Should return a UUID string
  6. Check the dashboard -- the click should appear in Analytics within seconds.

Troubleshooting

Snippet not loading

  • Verify the src URL is exactly https://cdn.selgeo.com/v1/selgeo.js.
  • Check for Content Security Policy (CSP) headers that may block the script. Add cdn.selgeo.com to your script-src directive.
  • Check for ad blockers that may block the script.

click_id is null

  • The visitor must arrive with a ?ref= parameter in the URL. Direct visits do not create a click_id.
  • Check that data-merchant contains a valid public key (pk_test_* or pk_live_*).
  • Verify the ref value matches an active tracking link in your program.
  • The link href must start with https://buy.stripe.com. Relative URLs or proxied URLs are not detected.
  • The rewrite only happens when a click_id is stored. Visit the page via a tracking link first.
  • If you set client_reference_id yourself, the snippet will not overwrite it.

Performance

The snippet is designed to have minimal impact on your site:

MetricValue
Bundle size< 5 KB gzipped
Initialization time< 50 ms
Network requests0 (no referral) or 1 (referral click registration)
Cookies setNone
DOM modificationsNone (except URL cleanup via history.replaceState)

The snippet runs entirely in an IIFE (Immediately Invoked Function Expression) and does not pollute the global scope beyond the __selgeo API object.

Next steps