SiliconPath Law Internal Documentation

Lead Token Service

Adds pseudonymous lead attribution to any website or landing page from a single script tag. A random token appears in that site's Google Analytics; the person behind it is resolved from our own database. No personal data ever reaches Google.

1. How it works

Visitor lands on a page carrying the snippet
   |
   +-- t.js mints a 22-character random token (128 bits)
   |
   +-- t.js finds the Calendly or HubSpot embed and threads the token through it
   |
   +-- visitor books or submits
   |
   +-- token + details  ->  our database   (personal data stays here)
   +-- token only       ->  dataLayer -> GTM -> GA4   (no personal data)

The token is a random label. It is not an encrypted or hashed version of anything, so there is nothing to decode and no key that could leak. It means nothing to Google and nothing to anyone reading the URL. Only our database can turn it back into a person.

2. Quick start

Two steps. Ten minutes, once per site.

Step 1: paste one line

In the site's <head>, before any Calendly or HubSpot embed markup:

<script src="https://track.siliconpathlaw.com/t.js?v=1"
        data-site="pk_yoursite_xxxxxxxxxxxx"></script>

That is the whole code change. No per-page work, and a new landing page on an already-registered site needs nothing at all.

Getting a key

Each site needs its own data-site key. Ask a developer to run php tools/track-newsite.php <slug> "<Name>" <domain>, which prints the key, the SQL to register the site, and this checklist filled in.

Is the key a secret?

No, and it does not need to be. It ships in the page source on every site. What protects the endpoint is a server-side check that the request really came from that site's registered domain, so a copied key cannot be used from anywhere else.

Step 2: configure that site's GTM and GA4

See section 4. It has to be done in each site's own container.

3. What is detected automatically

On the pageWhat happens
Calendly inline widgetToken appended to the booking URL as utm_content
Calendly popup or badgeSame
Calendly started from JavaScriptSame, by wrapping Calendly's own init call
HubSpot formName, email and phone captured on submit
Nothing recognisedToken is recorded, nothing else happens. No errors

Nothing is ever read from inside the Calendly window. That is another origin and cannot be read, which is why the token is passed in rather than details being pulled out.

Reporting a conversion from your own code

For a custom form the script does not recognise:

// on successful submit
window.splTrack.lead({ name: 'A Name', email: 'a@example.com' });

// on a confirmed booking or purchase
window.splTrack.conversion();

// the current token, if you need it
window.splTrack.token();

4. GTM and GA4 setup

This part is per site

Every site has its own GTM container and its own GA4 property, so this cannot be done once centrally. The names below are identical for every site, so it is the same checklist each time, never a judgement call.

In that site's GTM container

  1. Variable → New → Data Layer Variable
    Name: DL - lead_token  ·  Data Layer Variable Name: lead_token  ·  Version 2
  2. Trigger → New → Custom Event
    Name: CE - booking_complete  ·  Event name: booking_complete
  3. Tag → New → GA4 Event
    Event Name: booking_complete
    Event Parameter: lead_token = {{DL - lead_token}}
    Trigger: CE - booking_complete
  4. Preview, make a test booking, confirm the tag fires with the token populated
  5. Publish

In that site's GA4 property

  1. Admin → Custom definitions → Create custom dimension
  2. Dimension name: Lead Token
  3. Scope: Event
  4. Event parameter: lead_token
Do this before the site goes live

GA4 custom dimensions are not retroactive. Events collected before the dimension exists are never associated with it, and that data cannot be recovered. Register the dimension first.

Three traps

TrapWhy it matters
Choosing User scope User scope keeps only the most recent value per user, so a second booking overwrites the first. It must be Event scope.
Mapping the token to user_id That turns pseudonymous event tagging into cross-session user identification, which is a different thing under GDPR. Never do it.
Judging it by the standard reports on day one Reports lag 24 to 48 hours. Use DebugView to confirm arrival immediately.

5. Verifying an integration

In this order. The third is the one that is easy to skip and must not be.

  1. Browser console on the page: window.splTrack.token() returns 22 characters.
  2. The booking iframe's URL contains utm_content= followed by that same token. Inspect the iframe element, not the fallback link.
  3. GA4 DebugView: booking_complete arrives with lead_token populated.
  4. The database: the row exists.
    SELECT * FROM leads ORDER BY created_at DESC LIMIT 5;
  5. The Calendly booking record carries the token in its UTM data.
Step 5 is the real test

It is the only check that proves the token actually links to a person. Everything before it can pass while that link is silently missing.

6. Looking up a token

Marketing sends a token from Analytics. One query answers it:

SELECT s.slug AS site, l.page, l.name, l.email, l.phone, l.created_at
  FROM leads l
  JOIN sites s ON s.id = l.site_id
 WHERE l.token = 'PASTE_TOKEN_HERE';

The result includes which site produced it, so no guessing is needed first.

Other useful queries

-- recent leads for one site
SELECT * FROM leads_eb1a ORDER BY created_at DESC LIMIT 50;

-- totals per site this month
SELECT s.slug, COUNT(*) AS leads
  FROM leads l JOIN sites s ON s.id = l.site_id
 WHERE l.created_at >= '2026-08-01'
 GROUP BY s.slug ORDER BY leads DESC;

-- which landing pages convert
SELECT page, COUNT(*) AS leads FROM leads
 WHERE site_id = 2 GROUP BY page ORDER BY leads DESC;

-- tokens issued but never completed (visitor left without booking)
SELECT COUNT(*) FROM leads WHERE email IS NULL AND name IS NULL;

7. Troubleshooting

Symptom first, since that is what you have.

No token in the console

Token exists, but no row in the database

Row in the database, nothing in GA4

Token missing from the Calendly booking

Two rows for one visitor

Expected, and harmless. The first row is written when the page loads, the second when the booking completes. They share a token, so they are one row that was updated, not two leads.

8. Privacy

WhereWhat is held
Google AnalyticsThe token only. No name, email, phone, or hash of any of them
Our databaseName, email, phone, page, timestamp, and the token
CalendlyThe token in the booking's UTM data, alongside whatever the visitor typed into Calendly itself