GoHighLevel install

TrueMetriks tracks pageviews, leads, and purchases from your GoHighLevel funnels and forwards them to every ad platform you have connected. Here is how to set it up.

Set this up with AI

Copy this prompt into ChatGPT, Claude or whichever AI you use. It carries this whole guide, the pages it depends on, and a link to every video, so it can walk you through it one step at a time.

Open as text

Video guides

Install GoHighLevel tracking

Install GoHighLevel tracking

Payment plan and subscription automation

Payment plan and subscription automation

Custom events for forms and calendars

Fire custom events for GoHighLevel forms and calendars

Copy the tracking snippet from your dashboard

In your TrueMetriks dashboard, go to Settings > Tracking, pick the GoHighLevel tab, and click Copy on the Tracking snippet.

Showing setup for GoHighLevel

Install on GoHighLevel

One snippet picks up GHL form submissions, calendar bookings, and purchases automatically.

TRACKING SNIPPET

HTML
<script async src="https://q.yourdomain.com/t/s-ghl/abcd1234.js"></script>

GoHighLevel: Funnel settings → Tracking Code → Head. Paste, save, then test a form submission.

Checkout URL pattern

checkout
Click here if you have payment plans or subscriptions
Click here if you want to fire custom events for your GoHighLevel forms and calendars
Click here if you're using Typeform or Calendly
Settings → Tracking → GoHighLevel - copy the snippet, then paste it into your funnel

Checkout URL pattern. This is the word the tracker looks for in your URL to identify a checkout page. The default is checkout. If your funnels use a different word in their checkout URLs, change it in this field and click Save.

The card also has three expandable options - one for payment plans and subscriptions, one for firing custom events for your forms and calendars, and one for Typeform or Calendly. The first two are covered below.

Open the funnel in GoHighLevel

In the GoHighLevel left sidebar, click Sites.

Your Agency

Location

  • Launchpad
  • Dashboard
  • Conversations
  • Calendars
  • Contacts
  • Opportunities
  • Payments
  • AI Agents
  • Marketing
  • Automation
  • Sites
  • Memberships
  • Media Storage
  • Reputation
  • Reporting
  • App Marketplace
GoHighLevel sidebar - click Sites

At the top of the Sites page, click the Funnels tab.

Sites Funnels Websites Stores Webinars Analytics Blogs Forms

Funnels

Create and manage funnels to generate leads, appointments and receive payments.

Name Last updated
Lead Magnet Funnel Mar 06, 2026 02:03 PM
Spring Promo Mar 06, 2026 01:55 PM
Webinar Replay Feb 13, 2026 02:14 PM
Bookings Oct 01, 2025 04:23 PM
Click a funnel to open it (the highlighted row is just an example)

Click the funnel you want to track. You will repeat this for every funnel in your account - the snippet is the same.

Paste the snippet into Head tracking code

Inside the funnel, click the Settings tab. Scroll down to Tracking & scripts and paste the snippet you copied into the Head tracking code field. Then click Save.

← Back

Webinar Replay

Steps Stats Sales Security Events Settings

Tracking & scripts

Add third-party tracking and analytics scripts to your funnel.

Head tracking code

<script async src="https://q.yourdomain.com/t/s-ghl/abcd1234.js"></script>
Funnel Settings → Tracking & scripts → Head tracking code - paste the snippet, then Save

Repeat for each funnel.

Turn OFF Optimize JavaScript

Stay in the funnel's Settings tab and scroll down to Performance & compliance. Make sure Optimize JavaScript is switched off.

Performance & compliance

Improve performance and meet privacy requirements.

Image Optimization

All images used in this funnel will be optimized for speed and served via CDN with caching enabled.

</>

Optimize JavaScript

Custom javascript and html codes added will be lazy loaded for better page speed and performance.

GDPR compliant fonts

All pages in the funnel will be using GDPR compliant fonts instead of Google Fonts.

Funnel Settings → Performance & compliance - Optimize JavaScript must stay OFF (grey). The other two toggles are yours to set.

This one setting breaks tracking, and it is switched on per funnel, so a funnel that worked yesterday can stop working the moment somebody turns it on.

What it does to you. GoHighLevel's own description is "custom javascript and html codes added will be lazy loaded". Your tracking snippet is custom JavaScript, so it gets lazy loaded with everything else, and instead of running as the page opens it runs many seconds later. On a real customer funnel we measured the snippet loading 10,628ms after the page opened. With the setting off, the same funnel loaded it in 401ms.

What breaks in those ten seconds. The visitor is on your page and TrueMetriks is not running yet, so:

  • Plenty of people land, read, and click through before the tracker ever starts, and those visits are never recorded at all.
  • A visitor who moves on quickly can be counted as two separate people, because the click that identified them arrived before the tracker was ready. Their landing page and their thank-you page end up in two different sessions.
  • The ad click id can be missed, so the sale is not credited to the ad that produced it, and the conversion sent back to Facebook, Google Ads or TikTok carries no click id.

None of this looks like a broken install. The snippet is in the right place and the funnel works fine, you just get thin, split, badly attributed data.

Leave it off and keep it off. Check it on every funnel you track, and check it again if your numbers suddenly drop or your sessions start splitting in two. Image Optimization and GDPR compliant fonts in the same panel do not affect tracking, so set those however you like.

Payment plans and subscriptions (webhook)

If you sell payment plans or subscriptions, add one GoHighLevel automation that POSTs to the TrueMetriks webhook URL each time a payment lands.

Grab the webhook URL

Back in your TrueMetriks dashboard, on the same GoHighLevel install card, expand Click here if you have payment plans or subscriptions and click Copy on the webhook URL.

Click here if you have payment plans or subscriptions

If you sell payment plans or subscriptions, you need to add a webhook in your GoHighLevel automation to track these payments.

In GoHighLevel, go to Automation, create a new workflow with a Payment Received trigger, then add a Webhook action that POSTs to the URL below.

WEBHOOK URL

HTML
https://q.yourdomain.com/api/webhooks/ghl/abcd1234efgh5678ijkl90mn

You can also read the full guide by clicking the Open install guide button below.

Expand the accordion to reveal the webhook URL, then click Copy

Open Automation in GoHighLevel

In the GoHighLevel left sidebar, click Automation.

Your Agency

Location

  • Launchpad
  • Dashboard
  • Conversations
  • Calendars
  • Contacts
  • Opportunities
  • Payments
  • AI Agents
  • Marketing
  • Automation
  • Sites
  • Memberships
  • Media Storage
  • Reputation
  • Reporting
  • App Marketplace
GoHighLevel sidebar - click Automation

Create a workflow from scratch

Top right, click + Create Workflow, then + Start from Scratch in the dropdown.

+ Start from Scratch
Build Using AI
Select from Template
Import from a campaign
Company based workflow
Click Create Workflow, then Start from Scratch

Add the Payment Received trigger

In the new workflow, add a trigger and pick Payment Received from the list. Leave the trigger name as Payment Received (or change it if you want), then click Save Trigger.

Payment Received

Activates when a payment record posts successfully.

CHOOSE A WORKFLOW TRIGGER

Payment Received

WORKFLOW TRIGGER NAME

Payment Received
Pick Payment Received as the trigger, then click Save Trigger

Add the Webhook action

Below the trigger, add an action and pick Webhook (the normal one - not Custom Webhook). Configure it like this:

  • Method: POST
  • URL: paste the webhook URL you copied from your dashboard

Then fill in CUSTOM DATA with the keys in the table below and click Save Action. Leave Headers empty.

Fill in Custom Data on every workflow, including one built on GoHighLevel's own Payment Received trigger, and always map product to the merge field that holds the product name. Payment Received does send the amount, currency and transaction id on its own, but it identifies the product by an internal id rather than by its name, so without that one mapping your reports show a long code instead of what was sold.

Webhook

Fire a webhook containing the contact's details.

ACTION NAME

Webhook

METHOD

POST

URL

https://q.yourdomain.com/api/webhooks/ghl/abcd1234efgh5678ijkl90mn
Pick Webhook, set Method to POST, paste the URL, then click Save Action

Fill in Custom Data with these exact keys

The key names on the left are not free-form: TrueMetriks reads the sale from these keys, so they must be spelled exactly as shown. This matters most on a workflow that carries no standard payment data at all, such as one started by an Inbound webhook trigger (your payment processor, a Zap, or your own backend posts into GoHighLevel) where you build the sale yourself from custom values, but the same keys apply on every workflow.

METHOD

POST

URL

https://q.demo-brand.example/api/webhooks/ghl/abcd1234efgh5678ijkl90mn

CUSTOM DATA

These custom key-value pairs will be included along with the standard data

email
{{contact.email}}
amount
{{payment.amount}}
currency
{{payment.currency}}
product
{{payment.product}}
order_id
{{payment.transaction_id}}

Add another item

Custom Data: the key on the left must be spelled exactly as shown, the value on the right is the merge field from your own workflow

The left column is the key (fixed, copy it exactly). The right column is whichever merge field in your workflow holds that piece of data.

Key Required What the value must contain
email Required The buyer's email address. This is how the sale is matched to the person and their ad click.
amount Required The amount of this one payment, as a plain number (1995 or 1995.00). Currency symbols and thousands separators are accepted ($1,995.00).
currency Required The 3-letter currency code, for example USD, GBP, EUR. If you leave it out, USD is assumed.
product Required The name of what was bought, for example 1-1 Coaching Extension. This is the product name shown in your reports. If you leave it out, or map it to a product or price id instead of the name, your reports show that code instead of the product and any Facebook custom conversion that matches on the product name will not fire.
order_id Recommended The unique id of this payment or transaction. It is what stops the same sale being counted twice. If you leave it out, TrueMetriks generates one.
first_name, last_name, phone Optional Extra buyer details, which improve the match rate on Facebook and TikTok.

Two rules that stop wrong revenue

1. amount must never arrive empty. If the merge field you mapped to amount has no value for that payment, TrueMetriks falls back to the next money-like field in the payload and can record that number as your sale.

2. Send only one money field. Delete every other key that holds a number of money from the Custom Data list, for example revenue, total, cash_collected, payments, or a lifetime-value field. A running total is not the sale. This is the single most common cause of a purchase showing a much larger figure than the payment that was actually taken: a workflow mapped amount to a field that came through empty, and a revenue key next to it carried the customer's total cash collected to date, so that total was recorded as the sale.

Keep the list to the keys in the table above and the amount in your reports will always be the amount that was charged.

Publish the workflow

Top right, flip the toggle from Draft to Publish, then click Save.

YN
Draft
Publish
Flip the toggle from Draft to Publish, then click Save

For reference, your published automation should look like this:

Track Payments to TrueMetriks Test Workflow Draft
Payment Received
No filters applied
🗑 📊 Stats
+ Add New Trigger
+
Webhook
+
END
What the finished automation looks like: Payment Received trigger -> Webhook -> END

Fire custom events for forms and calendars

Custom events let you fire an extra, named Facebook event for one specific form or calendar, matched by its name, so you can build an audience or optimize a campaign around that one source. By default your standard Lead and Schedule still fire and record alongside it, and you can optionally switch that off so only your custom event fires for that one matched form or calendar (see Also fire the standard event below). For example: a newsletter_lead event only for your newsletter form, or a strategy_call_booking event only for your strategy-call calendar.

Video guide

Fire custom events for GoHighLevel forms and calendars

Open the custom events option and click Create

On the GoHighLevel install card in your dashboard, expand Click here if you want to fire custom events for your GoHighLevel forms and calendars, then click Create.

Click here if you want to fire custom events for your GoHighLevel forms and calendars

Fire a custom Facebook event for a specific form or calendar, matched by its name (the GoHighLevel "source"). Your standard Lead and Schedule still record in TrueMetriks. Created events appear under Facebook → Custom events, tagged GoHighLevel, where you can edit or remove them.

On the GoHighLevel install card, expand Click here if you want to fire custom events for your GoHighLevel forms and calendars and click Create.

Fill in the Create custom event popup

Create custom event

newsletter_lead
Source filter Optional

Only fire when the GoHighLevel form or calendar source contains this text. Leave blank to fire on every Lead. Case-insensitive.

Newsletter Signup
Also fire the standard event (Lead + newsletter_lead) This form records and fires both the standard Lead and newsletter_lead.
The Create custom event popup. Pick Lead for a form or Schedule for a calendar, type a custom name, choose when to fire, then paste the form or calendar name into the Source filter. Leave Also fire the standard event ticked to keep firing the standard event too, or untick it to fire only your custom event for that source.
  • Standard event. Pick Lead for a form or Schedule for a calendar. This is the most important choice: Lead is for forms, Schedule is for calendars.
  • Custom event name. Type any name you want, for example newsletter_lead. This is the name the event shows under in Facebook. Use letters, numbers and underscores.
  • Fire when. Leave it on Always, or choose New customers only / Returning customers only to fire just for first-time or repeat contacts. See New vs returning customers for what those mean.
  • Source filter. This is where you tell TrueMetriks which form or calendar to match. Type the name of the form (for Lead) or the calendar (for Schedule). The match is case-insensitive and a "contains" match. Leave it blank to fire the custom event on every Lead (or every Schedule) instead of one specific source.
  • Also fire the standard event. This checkbox only appears once you have typed a Source filter. Leave it on (the default) to fire and record both the standard event and your custom event, exactly as before. Turn it off to fire and record only your custom event for that matched source: the standard Lead or Schedule will not fire to Facebook and will not show up in your TrueMetriks reports. Use this when one specific form should count as its own conversion instead of a Lead, for example a registration form counted as complete_registration.

Where to find the form or calendar name

For a form, open Sites > Forms in GoHighLevel and edit the form. The name shown at the top is the source - copy it into the Source filter.

Back Newsletter Signup
In GoHighLevel open Sites → Forms and edit your form. The name at the top - here Newsletter Signup - is the source. Copy it into the Source filter.

For a calendar, open Calendars in GoHighLevel, edit the calendar, and look at Calendar name under Basic details. Copy that into the Source filter.

Back to calendars list Edit - Strategy Call

Basic details

Strategy Call
In GoHighLevel open Calendars, edit the calendar, and look at Calendar name under Basic details - here Strategy Call. Copy it into the Source filter.

Paste the name into the Source filter exactly as it appears, then click Create.

What you get after clicking Create

The event appears under Facebook > Custom events in your dashboard, tagged GoHighLevel with the source it matches. From here you can edit when it fires or remove it.

Custom events

Lead GoHighLevel newsletter_lead source contains "Newsletter Signup"
The saved event appears under Facebook → Custom events, tagged GoHighLevel with the source it matches. The green dot and check mean it is live.

TrueMetriks also creates a matching Custom Conversion inside Facebook Ads Manager (Events Manager > your pixel > Custom conversions). It starts Inactive and turns Active once the first matching event lands. Give it 30 to 60 seconds before you test.

Custom Conversions

  • Connect data
  • Overview
  • Datasets
  • Custom conversions
  • Integrations

Measure and Optimize with Custom Conversions

Use custom conversions to measure outcomes that happen on your website or in-store, and optimize your ads for URL traffic and custom events.

Q Search by name or ID
Custom Conversions Status Data Source Total custom conversions
Course Page View
ID 924925796383746
Active
My Site Pixel
ID 1234567890123456
228
Last received 8 hours ago
newsletter_lead
ID 1303950898573493
Inactive
My Site Pixel
ID 1234567890123456
0
Never received event
Facebook Events Manager → your pixel → Custom conversions. The newsletter_lead conversion is auto-created the moment you click Create in TrueMetriks. It starts Inactive until the first matching event lands.

Test it

Submit the form (or book the calendar) you filtered on. In Facebook Events Manager > Test events you will see both the standard event and your custom event arrive together - Lead plus your custom name for a form, Schedule plus your custom name for a calendar.

Receiving activity

ghltest.your-domain.com test_event_code: TEST89826

5 options selected
Events Received Received From Setup Method Event ID Time Received
Schedule Processed Server Manual Setup 019f02ec-a9ee-78... Today at 9:54:52 AM
strategy_call_booking Custom event Processed Server Manual Setup 72bc8865251381f... Today at 9:54:52 AM
PageView Custom event Processed Server Manual Setup 019f02ec-a6cc-79... Today at 9:54:51 AM
Lead Processed Server Manual Setup 019f02ec-3c98-79... Today at 9:54:24 AM
newsletter_lead Custom event Processed Server Manual Setup d077ec4bdeb3c89... Today at 9:54:24 AM
In Facebook Events Manager → Test events, both the standard event (Lead, Schedule) and your custom event fire together. Every row says Server because TrueMetriks is server-side.

Custom coded forms and calendars

If you built your own form or your own booking widget on a GoHighLevel page instead of using GoHighLevel's, TrueMetriks still tracks the visitor but it never learns that they submitted anything, so no Lead or Schedule conversion is recorded. One line of your own JavaScript fixes that.

When you need this

Only when the form or the booking widget is custom coded: your own HTML and JavaScript, or a third-party embed that is not a GoHighLevel form and not a GoHighLevel calendar.

A normal GoHighLevel form or calendar needs none of this. Those record their Lead and Schedule automatically, and adding the code below to one of them would count the same conversion twice. Only use it where you built the form or the booking widget yourself.

The symptom, if you are not sure: the person shows up in your dashboard with their email and phone and you can see their session, but no Lead (or no Schedule) ever appears for them.

Add the helper to your page

Paste this once into the funnel's Head tracking code, underneath your TrueMetriks snippet. A custom code block on the page works too, as long as it comes after the snippet.

<script>
function tmSendConversion(eventName, contact) {
  if (window.__tmCaptureIdentity) window.__tmCaptureIdentity(contact);
  if (window.tmFireEvent) window.tmFireEvent(eventName, {}, contact);
}
</script>

Optimize JavaScript must be off for any of this to work. With it on your snippet is lazy loaded, so it is not there yet when your form submits and the conversion is lost.

Fire Lead from your custom form

In your own success handler, after the submission has actually gone through:

// Form submitted successfully
if (!window.__tmLeadSent) {
  window.__tmLeadSent = true;
  tmSendConversion("Lead", {
    email: "[email protected]",
    phone: "+15551234567",
    first_name: "Jane",
    last_name: "Doe"
  });
}

Replace the example values with the ones the person actually typed into your form.

Fire Schedule from your custom calendar

Exactly the same shape in your confirmed-booking handler, with the event name changed to Schedule:

if (!window.__tmScheduleSent) {
  window.__tmScheduleSent = true;
  tmSendConversion("Schedule", {
    email: "[email protected]",
    phone: "+15551234567",
    first_name: "Jane",
    last_name: "Doe"
  });
}

What to put in the contact details

  • email is the one that matters. It is what ties the conversion to the visitor's session and to the ad click that brought them in. Send the real address they typed. A merge tag that has not been filled in, such as {{contact.email}} arriving as literal text, is ignored.
  • phone should carry the country code, for example +15551234567.
  • first_name and last_name are optional and can be left out.
  • Every field is optional in the sense that an event with no email still records, but it cannot be matched back to the person nearly as reliably, so send the email whenever you have it.
  • Lead and Schedule are the only two names to use here. They are the same conversions the dashboard and Facebook already understand, so they show up in your reports and fire to every connected ad platform exactly like a native GoHighLevel form would.

Two rules that stop double counting

1. Fire it once, and only when the submission actually succeeded. Put the call in your success path, after your own save or booking request comes back OK, never on the button click. A hand-fired conversion has no safety net here: two calls are two conversions in your reports and two conversions sent to your ad platforms. The if (!window.__tmLeadSent) guard in the examples is what stops an impatient double click sending it twice, so keep it in.

2. Do not also send the same form through a receiving webhook. If you have a GoHighLevel workflow POSTing this same submission to a TrueMetriks webhook URL, pick one or the other. Doing both records the conversion twice.

How to test

After installing the snippet (and the webhook, if you set one up), the next step is verifying everything is firing correctly. See Test your integration for the full walkthrough.

Something not firing? See Troubleshooting.

Frequently asked questions

Why must Optimize JavaScript be turned off?

Because it lazy loads your tracking snippet. GoHighLevel's own description is that custom javascript and html codes will be lazy loaded, and your snippet is custom JavaScript, so instead of running as the page opens it runs many seconds later. On a real customer funnel we measured 10,628ms with it on versus 401ms with it off. In that gap visitors are not tracked at all, a visitor can be split into two people so their landing page and thank-you page land in different sessions, and the ad click id can be missed so the sale is not credited to the ad. It is set per funnel, in Settings > Performance & compliance, so check every funnel you track.

Where do I find the tracking snippet?

In your TrueMetriks dashboard at Settings > Tracking > GoHighLevel. The snippet has a Copy button and is generated for your account.

Do I need to paste the snippet on every funnel?

Yes. GoHighLevel scopes the Head tracking code per funnel, so each funnel needs the snippet pasted into its own Funnel settings. The snippet itself is the same across all funnels in your account.

What is the Checkout URL pattern?

It is the word the tracker looks for in your URL to identify a checkout page. The default is checkout, which matches GHL checkout URLs. If your funnels use a different word, change it in your dashboard and click Save. The code does not change.

How do I fire a custom Facebook event for one specific form or calendar?

On the GoHighLevel install card, expand Click here if you want to fire custom events for your GoHighLevel forms and calendars and click Create. Pick Lead for a form or Schedule for a calendar, type a custom event name, and put the form or calendar name in the Source filter. The custom event then fires alongside the standard Lead or Schedule.

What is the Source filter and where do I find the name?

The Source filter is the name of the GoHighLevel form or calendar you want to match. For a form, open Sites > Forms and copy the form name. For a calendar, open Calendars > edit the calendar and copy the Calendar name under Basic details. The match is case-insensitive. Leave it blank to fire on every Lead or every Schedule.

Which standard event do I pick - Lead or Schedule?

Lead is for forms and Schedule is for calendars. Pick Lead to fire a custom event for a form submission, and Schedule to fire one for a calendar booking.

When do I need the webhook?

If you sell payment plans or subscriptions, the recurring charges happen after the customer leaves the page, so the script cannot see them. The webhook signals TrueMetriks every time a payment posts in GoHighLevel.

Do I need both the script AND the webhook?

For payment plans or subscriptions, yes. The script handles pageviews, leads, and the first purchase from the browser. The webhook handles every recurring payment after that.

Which Custom Data keys does the GoHighLevel webhook need?

Fill in Custom Data on every workflow, including one built on GoHighLevel's own Payment Received trigger, and use these exact keys: email, amount and product are required, currency is required unless your sales are in USD, order_id is recommended, and first_name, last_name and phone are optional. Map product to the merge field that holds the product name, not to a product or price id. Leave Headers empty.

My purchases show a long code instead of the product name. Why?

Because the workflow is not mapping product to the product name. GoHighLevel identifies the product by an internal id, so that code is what gets recorded and what your reports show, and a Facebook custom conversion that matches on the product name never fires. Open your workflow's Webhook action, add the product key under Custom Data, and map it to the merge field holding the product name. The full key list is in the Custom Data table on this page.

My form is custom coded and no leads are showing. Why?

A form you coded yourself does not tell TrueMetriks that it was submitted, so no Lead is recorded even though the visitor, their email and their session are all captured. Add the short snippet under Custom coded forms and calendars on this page and call it from your form's success handler.

Do I need this for normal GoHighLevel forms and calendars?

No. A GoHighLevel form records a Lead and a GoHighLevel calendar records a Schedule on their own, with nothing to add. The snippet is only for a form or a booking widget you built yourself, and adding it to a normal GoHighLevel form would count the same conversion twice.

Why does my purchase show a much bigger amount than the payment?

Almost always an extra money field in the webhook's Custom Data. If the field you mapped to amount arrives empty, TrueMetriks falls back to the next money-like key in the payload, so a revenue or cash collected key holding a running total gets recorded as the sale. Make sure amount always has a value and delete every other money key from Custom Data.

Need help with this?

Reach us instantly on WhatsApp, or send us a message and we will get back to you. On workdays we usually respond in less than 24 hours.

or send us a message