The Google Tag Manager integration loads the standard GTM snippet on your booking pages and salespads, and pushes structured salescal.* events into the dataLayer at key moments. You then wire those events to destinations (GA4, Google Ads, LinkedIn Insights, etc.) inside GTM — SalesCal doesn't talk to those tools directly.
Get your container ID from Google Tag Manager — it looks like GTM-XXXXXXX (uppercase letters and digits, no lowercase).
In SalesCal, go to Integrations > Google Tag Manager.
Paste your container ID and click Save.
The snippet starts loading on the next page view of any booking page or published salespad.
You can disconnect at any time from the same screen — the snippet stops loading immediately on subsequent page views.
One container per workspace. All your booking pages and salespads share the same GTM container. If you need separate environments (test vs production), use GTM's built-in environments feature inside your container.
Booking pages (the embedded widget and the standalone slide-form layout)
Published salespads (every page on your *.salescal.site subdomain)
The snippet renders before any custom head scripts you've added per salespad, so window.dataLayer is initialized before anything else runs.
It does not load on:
The SalesCal dashboard itself (app.salescal.ai)
The booking-widget preview inside the event builder (preview mode should never fire real events into your own browser session)
These fire from both the inline booking widget and the slide-form layout. Every event includes the same base payload — fields that don't apply are null.
salescal.potentialFires twice in the typical flow:
When the lead enters and submits their email
Again when the lead enters and submits their phone number (if the form asks for it)
Use this for top-of-funnel "engaged" events in GA4 / ad platforms.
salescal.qualifiedFires when the lead completes the form and passes all qualification rules. The next screen will be the calendar / time picker.
salescal.disqualifiedFires when the lead completes the form and fails one or more qualification rules. The next screen will be the disqualification page. Includes the matched rule's reason in disqualificationReason.
salescal.bookedFires when the lead picks a time slot and the meeting is created. Includes meetingId and scheduledAt.
{
"event": "salescal.qualified",
"leadId": "uuid",
"eventId": "uuid",
"eventSlug": "discovery-call",
"eventName": "Discovery Call",
"teamId": "uuid",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+15551234567"
}Extras per event type:
Event | Additional fields |
|
|
|
|
Fire from any published salespad on your *.salescal.site subdomain.
salescal.salespad_viewFires once when the salespad page mounts.
{
"event": "salescal.salespad_view",
"salespadId": "uuid",
"slug": "spring-launch",
"teamSlug": "acme"
}salescal.salespad_clickFires when a visitor clicks a tracked CTA on a salespad — Button blocks, Button Modal blocks, Image blocks with links, and Hero CTA buttons.
{
"event": "salescal.salespad_click",
"blockId": "uuid",
"blockType": "button",
"label": "Book a call",
"url": "https://...",
"clickAction": "link"
}The booking events push plain-text email, firstName, lastName, and phone into the dataLayer. If you need hashed values (for example, GA4 Enhanced Conversions or Google Ads Enhanced Conversions for Leads), hash them inside GTM:
In GTM, create a Custom JavaScript Variable
Read the raw email / phone from the dataLayer
Hash with SHA-256 (Google's Enhanced Conversions support libraries do this)
Pass the hashed variable to your tag instead of the raw field
Doing it inside GTM keeps the hashing logic in your hands and avoids us prescribing an algorithm you can't change.
Use Google's Tag Assistant to preview events in real time:
Click Preview in the top right of your GTM container
Enter the URL of one of your booking pages or salespads
Submit the booking form / click a CTA
Watch the events appear in Tag Assistant with their full payloads
If events don't appear:
Confirm the container ID is saved in SalesCal (Integrations > Google Tag Manager)
Confirm GTM's Publish workflow has actually shipped a live container (a brand-new container with no version published won't fire any tags)
Check the page source — you should see <script> containing googletagmanager.com/gtm.js?id=GTM-...
These events are on the roadmap but don't fire in v1:
Meeting reschedule, cancel, or outcome change (won, lost, no-show) — those happen on the manage-meeting and dashboard flows, which don't currently load GTM
Salespad scroll-depth or video-engagement events
Server-side events (everything is browser-side today)
Multiple containers per workspace
Per-event opt-out
If any of these matter, let support know — priority is driven by demand.