Skip to content
Proofbell

Install the tracking tag

One line in the <head> of every page. Your account gives you the exact snippet with your key already in it — copy it from Tracking rather than typing it out. That page also tells you whether we have seen the tag on each of your domains.

The snippet

<script src="https://api.proofbell.com/collect/t.js"
        data-ct-key="ct_your_key_here" async></script>

data-ct-key is your project's public key. It is safe to have in your page source — that is where it has to be — and it is restricted to the domains you list, which is what stops anyone else using it.

Add your tracking domains before you go live. A key with no tracking domains listed works on any site, so someone who copied it out of your page source could use it and consume your number allowance. Set them under Tracking.

If your site spans more than one domain

A brochure site on one domain and a booking or checkout flow on another is one journey to your customer and, to a browser, two unrelated visitors — the identifier that remembers someone is tied to the domain that set it and cannot be read from the other one.

List both domains and we join them up for you. When somebody follows a link from one of your domains to another, we carry their visit across, so the advert that brought them to the brochure site still gets the credit for the call they make from the booking page. Without it that call arrives as a direct visit to the second domain — no error, nothing to notice, just a channel report that quietly understates whatever is working.

The call itself is credited to the advert, not to the second domain. The visit on your booking domain keeps the campaign, the source and the click from the visit that started on your brochure site, so a last-click report says Paid Search rather than Direct. Two things worth knowing about that: the landing page still shows the booking page, because that is the page they actually arrived on; and if they arrive on the second domain by clicking a new advert, that new campaign wins — a fresh click is never overwritten by an older one.

It only applies to the domains you have listed. Specifically:

  • Links to anywhere else are untouched. A link to a supplier, a partner or a social network carries nothing — we do not hand your visitors' identifiers to third parties.
  • It lasts about two minutes. Long enough to follow a link, and deliberately not long enough for a copied link to matter: if somebody pastes that URL into a group chat an hour later, whoever opens it is counted as themselves and not as the person who sent it.
  • It disappears from the address bar. We remove it as soon as the page loads, so it will not be bookmarked, shared, or show up as a stray parameter in your own analytics.

Nothing to switch on: listing a second domain is what enables it, and a project with one domain behaves exactly as it did.

Where to put it

In <head>, before the closing tag. It is async, so it will not delay your page rendering.

PlatformWhere
WordPress A header-scripts plugin, or header.php in a child theme. Do not edit a parent theme — an update will overwrite it.
Shopify Online Store → Themes → Edit code → theme.liquid, inside <head>.
Wix / Squarespace Settings → custom code → header, applied to all pages.
Google Tag Manager Our tag template, on All Pages — see below. Works, but see the note about timing.
Hand-built siteYour base template or layout partial.

Tag Manager works but is slower. GTM loads, then loads us, so there is a window where a visitor sees your real number before the swap. They still reach you — it just is not tracked. A direct script tag in the head avoids that entirely, and is what we recommend if you can edit the template.

Google Tag Manager

We publish a tag template, so you enter your key in a field rather than pasting HTML into a Custom HTML tag. Import proofbell-call-tracking.tpl under Templates → Tag Templates → New → ⋮ → Import, then create a tag from it and fire it on All Pages.

It has one required field — your public key — plus an optional list of numbers to replace, an alternative script host, and a consent switch. The consent switch is on by default and gated on analytics_storage: until your consent tool grants it, the tag waits and your real number stays on the page.

Leave the host field alone unless we have given you a host. The field exists for a future white-label domain and for a reverse proxy you run yourself. White label is not built, so we do not currently issue anyone a Proofbell tag domain of their own — and a host we have not set up will not answer, which means the tag loads, finds nothing, and leaves your real number on the page with no error anywhere.

A Custom HTML tag still works if you would rather not import a template — paste the snippet above. The template exists so that a key does not have to be edited inside HTML, which is where people mistype it.

What the tag actually does

  1. Reads how the visitor arrived — referrer, UTM parameters, ad click identifiers.
  2. Asks us for a number for that visitor. The same person coming back gets the same number, so a call two days later still attributes correctly.
  3. Finds phone numbers in your page and replaces them, keeping your formatting. If your page says 01242 123 456 the swapped number appears as 01242 987 654, not +441242987654.
  4. Updates tel: links so tapping to call on a mobile uses the tracked number too.

How it recognises your number

By matching the last nine digits, so every way you have written it gets swapped without you listing variants:

  • 01242 123456
  • (01242) 123 456
  • +44 1242 123456
  • tel:+441242123456

Texts to your tracking numbers

If a tracking number can receive texts, they now arrive in Proofbell — under Texts to your numbers on the Calls page. Nothing to set up: a text to a tracking number is recorded the same way a call is.

You cannot reply from Proofbell yet. Reply from the phone the number forwards to and the conversation stays with your customer, where it belongs. We would rather say that plainly than give you a reply box that sends from a number your customer does not recognise.

Attachments are counted, not stored. If somebody texts you a photo we tell you there is one and it stays on your phone — we do not hold a copy of a file we never looked at and could not promise to delete.

Texts count towards your usage the same way calls do, by the segment count your carrier reports. A long message or one with emoji is more than one segment, which is the carrier's arithmetic rather than ours — we bill on the number we are billed on.

Tracking form submissions

Add data-ct-form to any form you want counted, with a name you will recognise in your own reports:

<form data-ct-form="contact-us" action="/thanks" method="post">

That is the whole change. The tag posts the submission as the form is submitted, without delaying it — if our server is slow or unreachable, your form submits exactly as it would have. Nothing we do here can cost you a lead.

Forms are opt-in, one at a time. Untagged forms are ignored, deliberately: a tag that counted every form would count your search box, your newsletter signup and your login, and your report would fill with submissions that are not enquiries.

What gets collected

The form's name, the visitor it came from, and — if the form has them — the email address and phone number, hashed. Nothing else, and no raw value is ever stored: we look for fields named email and phone (and a few common variants), hash them, and keep only the digest.

The message body is never collected. There is no way to send it to us even if you wanted to — the endpoint accepts those two fields and refuses everything else. That is a deliberate limit rather than an oversight: an enquiry form is where somebody types about their divorce or their diagnosis, and that text has no business in a call tracking database.

The two hashes exist for one job: recognising that the person who filled in your form on Tuesday is the person who rang on Friday, so you see one enquiry rather than two.

Forms that do not submit normally

A React form, or a third-party embed, often never fires a browser submit event — it intercepts the click and posts by itself. Call this from your own success handler instead:

window.proofbell.formSubmitted("contact-us", {
  email: values.email,
  phone: values.phone,
});

Either route is fine and you do not need both. If you use both on one form you will not get two submissions — each carries its own id and a repeat is discarded, which is also what protects you from a double-clicked submit button.

Where they appear

In your channel report, beside calls. That is the point of collecting them: if your paid search brings calls and your organic traffic fills in forms, a report counting only calls makes organic look like it does nothing — and the obvious decision from that report is the wrong one.

If something goes wrong, your real number stays visible

Deliberately. Every part of the tag is wrapped so that a failure leaves your page exactly as it was:

  • Our API unreachable → your real number, unchanged.
  • Your number allowance exhausted → your real number, unchanged.
  • A JavaScript error anywhere in the tag → your real number, unchanged.

You lose the tracking for that visit, never the call. A tracking script that can cost you a customer is not worth having.

How the number is written

By default the tag copies the shape of the number already on your page. If your site says 01242 123 456, the tracked number appears the same way; if it says +44 (0)1242 123456, so does the tracked one. Your design is untouched, and a page that writes its number two ways keeps both.

To use one format everywhere instead, choose it under How your number is written, in the Setup section of Account settings. Each option shows your own number rendered that way, so you can see the result before choosing it:

  • 01242 438 777 — national, spaced
  • 01242438777 — national, no spaces
  • +44 1242 438 777 — international, spaced
  • +441242438777 — international
  • +44 (0)1242 438 777 — international with the (0), spaced
  • +44 (0)1242438777 — international with the (0)

The spacing follows your area code, so a London number groups as 020 7946 0958 and a Cheltenham one as 01242 438 777. Outside the UK the digits are not spaced, because the conventions differ by country and a wrong one reads as foreign to a local.

If you need different formats on different sites, add data-ct-format="national_spaced" to the snippet on that site. The attribute wins over the setting in your account.

A format only applies where it can be written correctly. The (0) options are unavailable for countries that have no trunk digit — Spain, Portugal, Denmark and Norway — because telling a caller there to drop a digit that does not exist would be wrong. Where a format cannot be used, the tag falls back to copying your page, and your account shows that option greyed out rather than letting you pick it.

Numbers in images or Flash-style widgets

The tag can only swap text it can read. A phone number baked into an image, a <canvas>, or a third-party chat widget's iframe cannot be changed — so calls from those arrive as untracked. If your header number is an image, that is worth fixing for tracking and for accessibility.

Cookies, consent, and a limitation worth knowing

The tag sets one cookie, _ct_vid, to recognise a returning visitor so that a call two days after the click still attributes to it. It is HttpOnly — unreadable by any script on the page, including ours — Secure, and SameSite=Lax, which is what lets it survive the cross-site navigation of an ad click.

It holds a random identifier and nothing else. No name, no number, no email, and it is scoped to your project so it cannot follow anyone from one Proofbell customer's site to another.

Be aware: it is set on our domain, not yours. The tag calls api.proofbell.com, and the cookie belongs to that domain — which makes it a third-party cookie from your site's point of view. Safari's tracking prevention and Chrome's third-party cookie restrictions can therefore shorten or block it.

The practical effect is on returning visitors: if the cookie is dropped, someone who clicks an ad today and rings tomorrow may be treated as a new visitor, and the call attributes to however they arrived that second time. First-visit tracking — the majority of calls — is unaffected, because the number is issued during that visit.

A tracking subdomain on your own domain (track.yoursite.co.uk pointed at us) would make it genuinely first-party and remove the limitation. That is on our roadmap and not available yet; we would rather tell you than let you assume otherwise.

Consent

Under UK and EU rules a cookie used solely to deliver a service the visitor is requesting is generally treated as strictly necessary — but that is your call as the data controller, not ours. If your consent tool blocks scripts until consent is given, load ours in the same category as your analytics.

Next Tracking domains and verification