Agent-traffic tracker · v0.1

One line. It counts the AI assistants that visit your site.

People are starting to tell an AI assistant "book me a plumber for Thursday", and the assistant goes to a website and tries. This counts those visits, and it catches the ones where the assistant tried your form and could not finish.

That is the whole thing. It watches. It never touches your site, your forms, or your customers, and it has no way to.

It is free, there is no account to make and nothing to buy at the end of it. There is also no product behind it yet — nothing on this page connects to a hosted service, because there is not one. This is a measurement: nobody has an honest number for how much AI-assistant traffic ordinary service businesses actually get. You get the answer for your site, we get the answer across all the sites, and that is the entire trade.

  • Page weight2.3 KB on the wire
  • Cookies setnone
  • Time to removedelete one line

01 The one thing to do

The line

Paste this

<script async src="https://tracker.frontlatch.com/t.js"></script>

Select the text above and copy it — the button needs JavaScript, this does not.

It goes immediately before the </body> tag, on every page.

It is byte-for-byte identical on every website that installs it. There is no site ID, no account key and nothing to fill in — a site is recognised by its own domain name. If anyone ever hands you a version of this line with a code or a number in it, it did not come from us.

Where it must not go: not in the <head>, not inside a form, and not into a page-builder text widget that will escape the code and print it on the page as visible text.

02 Where it goes

Find your platform.

If you do not know which one the site uses, ask whoever built it, or try WordPress first — it is the most likely answer by a distance.

WordPress

Use a plugin rather than editing theme files — a theme update will wipe a direct edit, and then the tracker silently stops with nobody noticing.

  1. Plugins → Add New. Search for a "headers and footers" plugin. WPCode and Insert Headers and Footers are the two common ones. Install, then Activate.
  2. Open its settings. There is a box labelled Footer, or Body (end).
  3. Paste the line in. Save.

If your theme already has a "Footer scripts" or "Custom code" box — many do, under Appearance → Customise — use that and skip the plugin entirely.

WordPress with Elementor

  1. Elementor → Site Settings → Custom Code → Add.
  2. Paste the line.
  3. Set Location to Body – End. Publish.

Squarespace

  1. Settings → Advanced → Code Injection.
  2. Paste the line into the Footer box. Not the Header box.
  3. Save.

Wix

  1. Settings → Custom Code → + Add Custom Code.
  2. Paste the line. Apply it to All pages.
  3. Choose Load code once per page — not "once per visit", because we want every pageview counted.
  4. Place code in: Body – end. Save.

Shopify

  1. Online Store → Themes → the three dots beside your live theme → Edit code.
  2. Open theme.liquid, in the Layout folder.
  3. Find </body> near the bottom of the file. Paste the line on the line just above it.
  4. Save.

Google Tag Manager

If the site already uses GTM this is the fastest route of the lot.

  1. New Tag → Tag Configuration → Custom HTML.
  2. Paste the line.
  3. Triggering: All Pages. Save.
  4. Hit Submit to publish. A GTM container does not go live until you Submit — this is the step everybody forgets.

Plain HTML site

Hand-built, or built by a developer years ago.

  1. Paste the line just above </body> on every page.
  2. If the site has a shared footer include — footer.php, footer.html, _footer.inc or something like it — put it there once and every page picks it up.

03 60 seconds

How to tell it is working

  1. The quick check

    Load any page of the site, right-click → View Page Source, and press Ctrl+F (Cmd+F on a Mac) for t.js. If the line is there, it is installed.

  2. The real check

    Press F12 to open the browser developer tools, click Network, reload the page. You should see t.js load with status 200. Now click through to another page or close the tab: a request to /b fires and comes back 204. That 204 is the collector saying "received".

  3. The lazy check, and honestly the best one

    Tell us the domain and load a couple of pages. We see the site appear at our end within a minute and confirm back to you.

04 Read this before you decide it is broken

Your own browser may be switching it off — on purpose

Brave and the DuckDuckGo browser send Global Privacy Control by default. Firefox sends it if you have ticked "tell websites not to sell or share my data". Some privacy extensions send Do Not Track.

When either signal is present the tracker stops before it starts: no listeners, no counting, no request. That is exactly what it should do — and it makes your own test look like a failure, because you are the visitor who asked not to be counted.

Test in Chrome or Safari with no privacy extension, or use the lazy check above and let us confirm from our end.

If the line is there and nothing arrives

Global Privacy Control or Do Not Track in your own browser
The big one, above. Brave and DuckDuckGo assert it by default and the tracker obeys it, so your own visit is invisible by design.
An ad blocker in your own browser
Try a private window, or a different browser.
A caching plugin still serving the old copy of the page
Clear the cache. WordPress caching plugins are the usual culprit.
A GTM container that was saved but never submitted
Saving a tag is not publishing it. Open the container and hit Submit.
The line went into the <head>, or into a text widget
In the head it can still work, but a page-builder text widget will print the code on the page as visible words instead of running it. If you can see the line on your site, that is what happened.

05 Measured, not estimated

What it does to the site

File size
5,686 bytes minified · 2,308 bytes gzipped (2.3 KB on the wire)
Loading
async — the browser never waits for it, so it cannot delay your page appearing
Requests
one per pageview, sent as the visitor leaves the page or after 20 seconds, whichever comes first. Never during loading
Typical request size
about 200 bytes; about 600 bytes on a pageview with a filled six-field form
Listeners
all registered passive — the browser’s own guarantee that a script cannot make scrolling stutter
Changes to your page
none. No markup added, no styles changed, no redirects, nothing done to your forms

One ordinary photo on your homepage is forty to a hundred times bigger than this file. The whole snippet is wrapped so that if it ever hit a bug it stops quietly and your page carries on as though it were not there — and that is not a promise on trust: the test suite runs the actual built file against a fake page and fails the build if it throws.

Measured 26 Aug 2026 against the live endpoint. The collector URL is baked into the file, so its length moves these figures by a byte per character.

06 One step

How to take it off

Delete the line. That is the entire removal.

There is nothing else to undo: no cookie to clear, no account to close, no plugin left behind, no file on any visitor’s computer. Do it at 2am without telling us and nothing breaks at either end.

If you want the visit counts already collected deleted as well, say so and they are deleted — though there is nothing in them that names anybody, which is the next section.

07 Checked against the code, not the README

What it collects, and what it never collects

Written so you can hand it straight to anyone who asks — a customer, your web person, your lawyer. Every line below was checked against the code on 25 Aug 2026, not against what would be nice to say.

What it collects on each page view

  • Your own domain name, and a shortened version of the page address. Never the query string — nothing after a ? is collected. The address is cut down in the visitor’s own browser, before anything is sent: only the first part survives, and only if that part does not look like it identifies somebody. A booking page at /patients/jane-smith-0412345678/appointment leaves the browser as /patients/*. An address that is just a phone number leaves as /*. An ordinary page like /book-a-plumber comes through as it is, because it names a service rather than a person.
  • The date and time of the visit.
  • Which site the visitor came from, as a domain only: chatgpt.com, google.com. Never the full link.
  • The browser’s user-agent string, kept with each visit and cut off at 256 characters — the same line of text every web server on earth already receives on every request.
  • Signals that tell software apart from a person: whether the browser admits it is automated, how many languages and plugins it declares, the window size, and counts of mouse, scroll and keyboard events. These describe the software. None of them describe the person.
  • If somebody uses a form: the names and types of the fields ("email", type email), how long each took to fill, how many keystrokes went into it, and whether the form succeeded, was rejected, hit a CAPTCHA, or was abandoned.
  • Password, hidden and file-upload boxes are not watched at all — not the value, not the name, not the type, not the keystroke count. The code does not create a record for them in the first place. If a form is rejected and the box that failed was one of those, the rejection is still counted but the box is not named.

What it never collects

No cookies
Nothing is stored on the visitor’s device at all — no cookie, no local storage, nothing. Nothing to clear, and nothing that follows them anywhere.
No identifier
No visitor ID, no fingerprint, no cross-site tracking — nothing is created or stored whose job is to recognise a visitor or tie two visits together. The one honest limit on that: each record holds the user-agent string and the window size, so somebody with the raw file could make an educated guess that two visits came from the same browser. There is no identifier in there to make it more than a guess, and nothing we build does it.
No IP addresses
The tracker never reads one, never stores one and never writes one to a log. Being complete about it: the collector is a web server, so the machine hosting it sees the connection the way every web server on the internet does. The address does not go into the record.
No form contents. Ever
Not the names, not the phone numbers, not the email addresses, not the message text. The only question the code ever asks about a text box is whether it is empty or not. The value is never copied into a variable, let alone sent anywhere.
No tick-box answers
For a checkbox or a radio button the ticked state is the answer — consented to marketing, has private health cover, is over 18 — so the code does not read it at all. It records that the box was interacted with, and when. Never which way it was set.
No error-message wording
A website can put anything it likes into its own "please fill this in correctly" messages, including a customer’s own name. So the message never leaves the page. It is matched against a fixed list of nine plain words — required, email, number, format, length, range, select, url, other — and only that one word travels.
Nothing at all from a visitor who has asked not to be tracked
If the browser sends Global Privacy Control or Do Not Track, the tracker stops before it starts: no listeners, no counting, no request. That visit is invisible to us, which is the point.
Nothing sold and nothing shared
The data is used for one thing: counting agent visits and finding the ones that failed. It goes to no third party.
Kept for 60 days, then deleted automatically
Not a policy somebody has to remember — the system prunes it on write. Earlier if you ask, no reason needed. The consequence, so you hear it from us: nothing survives expiry, not even an aggregate, so a report cannot show a trend older than 60 days.

Two limits we would rather tell you than have you find

A one-word address at the top of your site is kept as it is
The shortening described above cannot tell /jane-smith from /hot-water-repair — one is a person, one is a service, and they are the same shape. If your site has pages named after individual people or customers at the top level, do not install this yet. Tell us and we will add the ability to exclude those pages before you do.
The count of keys pressed on a page includes keys pressed into a password box
Even though the box itself is not watched. So on a page whose only input is a login, that count is roughly the length of a password. It was left in deliberately: without it, somebody who only typed a password would look like a browser with no human activity at all, and the tracker would wrongly call a real person a robot — which is the exact mistake it exists to avoid. Most service-business pages have no login on them.

Why it is built that way: the question being answered is about software, not about people. Counting which robots visit your site does not require knowing who your customers are, so the tracker is built to ask for as little about them as it can — and where something could still slip through, the two limits above say so rather than hoping you do not ask.

Does this mean I need a cookie banner?

It sets no cookies and stores nothing on the visitor’s device, so the thing that normally triggers a banner is not there. We are not lawyers and this is not legal advice — your privacy policy is your call.

If your policy lists what the site collects, a fair line to add is:

a script that counts automated and AI-assistant visits, which stores nothing on your device and collects no personal information.

08 And what not to expect

What you get back, and what to expect

A weekly report by email, one page, for your site

  • The number: how many visits that week came from an AI assistant acting for a person, and whether that is up or down on the week before.
  • Two separate lines underneath it: how many visits came from AI crawlers (the robots that read the web to train and index — GPTBot and the rest), and how many were people who arrived by clicking a link inside an AI answer. Neither is ever added into the headline number. Most tools would add all three together and show you a big number, and the big number would not mean anything.
  • Any failed agent action, written out in full: which page, which form, which field it died on, and how. If an AI assistant tried to book you and could not, you will see exactly where it gave up. That is the single most valuable thing this can find.

A straight expectation, so nobody is disappointed in three weeks

  • The number may sit near zero for a while. That is a real possibility, and we said so in writing before we started. If it does, that is not a broken tracker — it is the finding, and it is worth having.
  • This is a 60-day measurement, not a dashboard to check daily. Install it, forget it, read the weekly email. If something interesting turns up we will ring you rather than wait for the Friday report.

There is a page showing exactly what the report looks like, including what it looks like when the answer is zero: the dashboard.

09 Asked by real people

Questions people actually ask.

Will it slow my site down?
No. 2.3 KB on the wire, loaded async, one small request per pageview sent as the visitor leaves. The numbers are above.
Could it break my booking form?
It never touches the form. It cannot read what anyone types, cannot submit anything, cannot stop a submission, and has no code path to any of those. It is also wrapped so that a bug in it cannot surface into your page.
Will it hurt my Google ranking?
No. It is 2.3 KB on the wire, it loads async, and it adds nothing to the page.
Are you going to contact my customers?
No — and we could not if we wanted to. There are no names, no email addresses and no IP addresses in the data. There is nothing in it to contact anyone with.
Can I see the code before I paste it?
Yes. Ask, and you get the readable version — 137 lines with all the comments left in. Nobody was ever talked into installing something by being refused a look at it.
Can I host the file myself instead?
Yes. Ask for the built file and serve it from your own CDN. It is a static file with no callback to us beyond the beacon.
Who else has this on?
Ask on the day and you will get the real count, not a flattering one.

10 For an agency or a web person

Forwarding this to a client

If you are an agency or the web person and the decision is not yours to make, the block below is written to be sent to a client without editing. Copy it, paste it into an email, change nothing. Do not soften it and do not strengthen it — it is a promise made on your behalf and it has to be one we can both stand behind at a client’s kitchen table.

  • The line is byte-for-byte identical on every site: no site ID, no account key, no per-client config, nothing to get wrong on site 14 of 20. That is what makes a book-wide install one pass rather than a project.
  • A shared GTM container across the book is one Custom HTML tag, All Pages trigger, Submit — done in one action for every site in the container. A shared WordPress theme or a management plugin (ManageWP, MainWP) is one footer-snippet push.
  • To confirm the pass worked, send the domain list. Site attribution is the hostname and nothing else, so we can tell you which are reporting and which are not without a per-site checklist.

You can also simply send someone this page. It is the same information, it needs no editing, and it does not ask the reader for an email address or anything else.

Send to a client, unedited

We are adding a small script to your website that counts visits from AI assistants — the ones sent by somebody who asked ChatGPT or a similar assistant to find or book a service. It is one line of JavaScript, it is free, and here is exactly what it does and does not do.

WHAT IT COLLECTS ON EACH PAGE VIEW
- The site’s own domain name, and a reduced page path. Never the query string. The path is cut down in the visitor’s browser before anything is sent: only the first segment survives, and only if it carries nothing identifier-shaped.
- The date and time of the visit.
- Which site sent the visitor, as a domain only (e.g. chatgpt.com). Never the full link.
- The browser’s user-agent string, truncated at 256 characters — exactly as every web server already receives it on every request.
- Signals that distinguish a person from software: whether the browser reports itself as automated, how many languages and plugins it declares, the window size, and counts of mouse, scroll and keyboard events. None of these identify a person. They describe the software.
- If a form is used: the names and types of the fields, how long each took to fill, how many keystrokes were involved, and whether the form succeeded, was rejected by validation, hit a CAPTCHA, or was abandoned.

WHAT IT NEVER COLLECTS
- No cookies. Nothing is stored on the visitor’s device at all.
- No identifier. No visitor ID, no fingerprint, no cross-site or cross-visit tracking. The honest limit on that claim: each record holds the user-agent string and the window size, so someone with the raw data could form an educated guess that two visits came from the same browser. There is no identifier that would make it more than a guess, and nothing in the system attempts it.
- No IP addresses. The tracker never reads, stores or logs one. To be complete: the collector is an HTTP server, so the machine hosting it sees the connection as every web server does. The address is never put into the visit record.
- No form contents, ever. The names typed in, the phone numbers, the email addresses, the message text — none of it is read, stored or transmitted. The only question the tracker ever asks about a text field is whether it is empty.
- No password, hidden or file-upload fields. Not the value, not the name, not the type, not the keystroke count.
- No tick-box answers. For checkboxes and radio buttons the ticked state is the answer, so the tracker does not read it at all. It records that the box was interacted with and when; never which way it was set.
- No error-message wording. A site can put anything into its own validation messages, including a customer’s name, so the message never leaves the page: it is matched against a fixed list of nine generic reasons and only that one word is sent.
- Nothing at all from a visitor who has opted out. If the browser asserts Global Privacy Control or Do Not Track, the script stops before it registers a single listener.
- Nothing sold, nothing shared. It goes to no third party.
- Kept for 60 days, then deleted automatically. Enforced by the system on write, not by a policy someone has to remember.

TWO LIMITS, DISCLOSED RATHER THAN GLOSSED
- A one-word address at the top level is kept as it is. The path reduction cannot tell /jane-smith from /hot-water-repair — they are the same shape. If the site names top-level pages after individual people, say so before it goes on.
- The page-wide count of keys pressed includes keys typed into a password box, even though the box itself is not watched. On a page whose only input is a login, that count is roughly the length of a password. It was kept deliberately: without it, someone who typed only a password looks like a browser with no human input, which produces a false "agent" verdict.

REMOVAL: delete the line. There is no cookie to clear, no account to close, and nothing left on any visitor’s device.

Select the text above and copy it — the button needs JavaScript, this does not.

After you paste it

Send the domain. We watch for it at our end and confirm it is reporting, usually within the hour. If it is not reporting we tell you which of the five reasons above it is, rather than leaving you to guess.

Nothing on this page signs you up to anything, and pasting the line does not create an account, because there are no accounts.