Back to App
Back to Clients

Counting Trial Goals (events webhook)

A trial is almost always judged on a number: ten appointments booked, three deals closed, fifty leads delivered. The trial events webhook is an address your CRM calls every time that number goes up by one: SalesControl keeps the count for you and, once the target is reached, marks the trial as passed without anyone having to remember.

There is one address for the whole agency: you set it up once and reuse it in every client’s workflow, GoHighLevel snapshots included. Working out which client an event belongs to is SalesControl’s job, based on what the message carries.

Plan required

This feature requires a paid plan (Starter and above). See Subscription Plans.

Where to set it up

Open the Admin Panel and go to the Integrations tab: the Trial events (webhook) card is reserved for admins. The target and the window, instead, live where contracts live: on the Services page and in the client form.

Creating the address

Click “Generate address”

Until you do, the card says no address has been generated. One click creates the agency token and shows the full address, which ends with /functions/v1/trial-events?t=a1b2c3…: the part after t= is the token.

Copy the address

The Copy address button puts the full address, token included, on your clipboard. It is the same for every client: you don’t need one per client.

Paste it into your tool

In GoHighLevel: Automations › Workflow › add the Webhook action with the POST method at the point where the event happens (after an appointment is booked, for example). In Zapier or Make: Webhooks module, POST method, then build the JSON body with the fields below.

Grab the ready-made templates

In the card, How to connect it (GHL / Zapier / Make) opens the instructions along with two ready-to-copy JSON bodies, one for GoHighLevel and one for Zapier or Make.

The accepted fields

The minimum requirement is that either the external key or the client name arrives: with neither, the message is rejected, because there would be no way to tell whose event it is. Everything else is optional.

FieldRecognised keysWhat it’s for
External keyexternal_id, location_id, source_idA stable identifier for the client in your CRM. In GoHighLevel it is {{location.id}}.
Client nameclient_name, location_name, business_name, nome_business, name, nomeThe name the client is registered under in SalesControl. It is what the first match uses.
Event labelevent, evento, event_label, event_type, tipo_eventoFree text shown in the log. The templates use goal: leave it, or write the unit you are counting. It never changes the count.
Event idevent_id, idempotency_keyThe identifier of the appointment or the deal: it stops the same event from being counted twice.
Event dateoccurred_at, event_date, data_evento, date, data, timestampWhen it happened. If it is missing or unreadable, the time of arrival is used.
Note

Key names are read case-insensitively, so LOCATION_ID is worth the same as location_id. Underscores, however, are not ignored: the camelCase forms that are recognised are only the ones with an explicit alias — locationId, sourceId, clientName, locationName, businessName, eventId, idempotencyKey. For every other field use the underscore form: occurred_at, event_date, event_type. Dates are accepted both as DD/MM/YYYY and as YYYY-MM-DD; if the format can’t be read the event is still recorded, using the time it arrived.

The GoHighLevel shape

GHL doesn’t send every field at the same level: workflow custom values end up inside customData. The webhook reads customData, the top level and contact alike. When the same key appears twice, customData wins, then the top level, then contact — but a custom field left empty never wipes out the standard value with the same name.

Never count the same event twice

When an automation doesn’t get an answer quickly, it tends to retry: without a safeguard the same appointment would be counted several times and the trial would pass too early. That is why it pays to always send event_id with the identifier of the appointment or the deal: if the same identifier comes back, SalesControl answers ok but does not increase the count.

The same safeguard covers the most common slip when you are wiring up a lot of automations: the same address pasted into two or three different workflows that fire on the same fact. The event arrives several times there too, but with event_id filled in it is counted only once. Without event_id, SalesControl has no way of knowing it is the same fact and counts every call.

Counting an event from a GoHighLevel tag

With the GoHighLevel app connected you need no workflow at all: the tag that counts for the trial is set as a rule in the GoHighLevel tag events card (Admin › Integrations › Webhooks), with scope Clients’ sub-accounts and action Counts for the trial. The Trial events (webhook) card points you there with the Go to the rules link; a tag you had already set there has become a rule on its own. Every time a contact in the sub-account of a client with a running trial gets that tag, the trial counts one event: to count the same contact again, the workflow has to remove and re-add the tag. It applies only to clients with a connected sub-account. In the client page’s event log these events carry the GHL tag badge. Target, window and trial closing stay as always, and the webhook address keeps working for anyone not using GoHighLevel.

How an event finds its client

On arrival, every event is matched to a client in two steps:

The first successful match learns the link: the external key is saved on the client and from then on later events find it straight away, even if the name in your CRM changes. A client that already has a key is never silently re-linked to a different one.

Events left without a client

Whenever events are waiting, a yellow band appears at the top of the Clients page — admins only — with the count and a Sort them out button. It opens the Trial events to attach window, where each event shows the name and key that arrived, the date and, for ambiguous cases, the candidate clients.

Target and window: where you set them

Two values drive the automatic outcome, and they live on two levels:

WhereFieldsEffect
Services (the template)Trial event target, Trial window (days)The defaults for every client starting on that service.
The client form (when the Trial checkbox is on)The same two fieldsThey apply to that client only. Left empty, the service values are used.

On creation the two fields are pre-filled with the values of the service you pick; when editing they show what is currently set on the client.

Note

With no target, events are still counted and shown: they simply never close the trial on their own. It is the easiest way to start measuring before you decide what the right threshold is.

The window does not start at signature, but on the day you press 🚀 Activate campaigns in the Clients list: until you do, there is no deadline at all. See Managing the Trial Period.

What you see while the trial runs

The label on every row of the log is exactly the text you put in the event field: the templates use goal, and leaving it that way is perfectly fine. If you prefer, write the unit you are counting — appointment, contract, lead — so whoever reads the log sees at a glance what it is about. It makes no difference to the count: every event is worth +1, whatever label it carries.

Admins can correct the count: Add an event by hand records an event your CRM never sent, while the bin icon on a row excludes it — the event stays in the log as a trace, but stops counting.

Note

An event attached to a client is always counted, even if it arrives before campaign activation or once the trial is already closed. The target and the window decide the outcome, never the count.

When the target is reached

If the client’s trial is running and the count hits the target, the trial is automatically closed as passed, with the same effects as the manual button: the contract becomes active (installment due dates stay as calculated at signing), any retroactive bonuses tied to the signing month kick in, and the closure is recorded in the client timeline as a system action.

When the target is reached thanks to a manual correction instead, the card shows a Mark trial as passed button: closing it stays your call, with the same effects.

When the window expires without the target

The check runs once a day and you decide what happens, with the Automatic failure at the end of the window checkbox in the card:

Caution

If automatic failure is off and the Trial Window Expired notification is disabled on both channels, nothing happens when the window ends: the trial stays open and you only notice from the badge in the list. If you rely on the warning, switch it on.

The notifications

Three notifications follow the trial lifecycle, and they are off by default on both channels. You switch them on in Admin Panel › Notifications:

NotificationWhen it fires
Trial PassedThe trial is passed, either by reaching the target or by closing it manually.
Trial FailedThe trial is closed as failed, by automatic failure or manually.
Trial Window ExpiredThe window ends without the target being reached, with automatic failure off.

Recipients are chosen channel by channel among setter, closer, assigned PM, admin and sales manager. The client is available on email only, because clients have no push notifications: if there is no email address on their record, they are simply skipped.

Managing the address over time

Caution

The address contains a token: whoever holds it can push your agency’s trial counts up, and therefore make trials pass. They cannot read or change anything else. Treat it as a credential, share it only with whoever configures the automations and, if it ends up in the wrong place, use Regenerate token.

If something doesn’t work