Track every booked call, once, in every tool.
This guide is for the DeskTeam360 team that will build the tracking for the two new Google Ads landing pages. The pages are built as GoHighLevel funnels on open.deskteam360.com. The guide covers how to build them in GHL, plus Google Tag Manager, Google Analytics 4, Google Ads and Microsoft Clarity. Follow the parts in order. Every part ends with a "Done when" check.
0Read this first
What we are building
Someone searches on Google, clicks our ad, lands on one of the two pages and books a call in the calendar. When that happens:
gclid and our UTMs to the URLgclid and UTMs into the GHL calendar| Tool | What it records for a booked call | Why |
|---|---|---|
| GoHighLevel | The appointment, the contact, the gclid, UTMs, landing page and role. Tags and an opportunity. | Source of truth. This is where real calls are counted. |
| Google Ads | DT360 - Booked Call (browser), sent by GTM when the thank-you page loads. This is the only conversion Google bids on. | Google learns to find people who book, not people who visit. |
| Google Ads (check) | DT360 - Booked Call (GHL), sent from a GHL workflow. Secondary. | A second count from the CRM, to catch bookings the browser missed. Never bids. |
| GA4 | Event booked_call (key event), plus page views, CTA clicks, calendar views and scroll. | Shows which page, role and keyword brings bookings. |
| Clarity | Session recordings and heatmaps, with a booked_call event and page tags. | Shows where people stop reading or get stuck. |
Rules for this setup
- Do not change, pause or delete any existing Google Ads conversion action, goal or campaign. Rodrigo creates the two new actions himself (Part 4).
- Only the two landing pages get this setup. Do not add GTM or new tags to the main deskteam360.com site. It already has GA4, Google Ads and Meta tags in its code, and a second copy would count everything twice.
- Do not add Meta pixels to the landing pages yet. The main site loads three different pixels and we first need to know which one is the right one.
- No passwords, ever. Give Rodrigo access with his email, rodrigopatria@gmail.com. Send API tokens through a one-time secret link (for example 1Password, Bitwarden Send or onetimesecret.com), not in email, WhatsApp or a group chat.
- Test bookings use the name
TEST DT360and an email you own with+dt360testin it (example:yourname+dt360test1@deskteam360.com). Cancel them after the test.
Before you start
- Pages live in GoHighLevel. Both pages are GHL funnels on
open.deskteam360.com. The BI-1 page already exists (funnelDT - Google - Ad1 - Hire, path/dt-ad-hire). Part 8 says exactly how each funnel must be set up. Do not move the pages anywhere else. - Calendar: create the new one (decided). Make one new GHL calendar for ad traffic,
DT360 - Google Ads Call, a copy of "DeskTeam360 Demo Call 1" (Part 6.3). Two reasons: after booking it sends people to the ads thank-you page, which the main site's calendar must not do; and it keeps referral and website bookings out of the Google Ads numbers. - Page files. Download both pages here: dt360-landing-pages.zip. Preview: BI-1 hiring page, BI-4 white-label page. The BI-4 page is written and approved; it only needs to be built in GHL.
- What "BI" means. BI = Big Idea: the main message of an ad group and its page. We wrote four (BI-1 to BI-4) and start with two: BI-1 "The only hiring call you'll ever need" (entrepreneurs who want to hire) and BI-4 "Your agency's pit crew" (agency owners who need white-label help). BI-2 and BI-3 come later and will follow the same setup.
- Scope of this phase: booked calls only. We track up to the booked call. Paid clients ("New client") come later (Appendix B).
Order of work
Parts 2 to 6 create the accounts and IDs. Part 7 uses those IDs to build GTM. Part 8 puts GTM on the pages. Part 9 tests. Part 10 sends Rodrigo everything he needs.
| Part | What | Who | Gives you |
|---|---|---|---|
| 2 | Create the GTM container, give Rodrigo Publish | DeskTeam360 | Container ID GTM-XXXXXXX |
| 3 | Create the Clarity project, add Rodrigo, create the API token | DeskTeam360 | Clarity project ID, API token |
| 4 | Rodrigo creates 2 Google Ads conversion actions and sends you the label. You check auto-tagging and link GA4 | Rodrigo + DeskTeam360 | Conversion label (from Rodrigo) |
| 5 | GA4: key event, custom dimensions, filters | DeskTeam360 | Nothing new (uses G-ZSLFPBZD33) |
| 6 | GHL: fields, form, calendar, Google Ads link, workflow | DeskTeam360 | New calendar ID |
| 7 | Build GTM: variables, triggers, tags | DeskTeam360 | Published container |
| 8 | Build the pages in GHL funnels: content, calendar, thank-you page, SEO, tracking code | DeskTeam360 | Live URLs |
| 9 | Test booking on both pages | DeskTeam360 | Screenshots |
| 10 | Send everything to Rodrigo | DeskTeam360 | Rodrigo sets the bidding goal and runs the real ad-click test |
1The two pages and what they carry
We start Google Search with two ideas, one ad group and one page each. The pages have the same structure on purpose, so the test compares the message, not the layout. On both pages, every button scrolls to the calendar (#book) and the calendar is the only way to convert. There are no outbound links, no other form and no checkout. The page files are set to noindex so they do not compete with the main site in Google search. (The live GHL page lost that setting; Part 8 puts it back.)
"Your agency's pit crew. Everyone your agency needs, in one hire."
- File
bi4-white-label-pit-crew.html- URL
open.deskteam360.com/dt-ad-white-label(not built yet)- Who it is for
- Agency owners who need white-label web development, design and more, under their own brand.
- They searched
- white label web development, white label web design, white label wordpress, white label gohighlevel, white label agency services
- Main message
- Say yes to the next project without a new hire. The same crew on every client. A North American point of contact who talks with you, never your clients.
- Proof on page
- 12+ years, 400+ clients, 1-3 day turnaround, up to 3 tasks at once. Agency quotes: The Tobie Group, First Call Digital, Smash Wave, Sidekick, Duct Tape Marketing, Charisma Ink., Sidecar, Convert on Command.
- Offer line
- From $1,497/mo, no contracts, 30-day full refund
- Button text
- "Book your crew call"
- Tracking value
lp_variant = bi4_white_label
"The only hiring call you'll ever need."
- File
bi1-hire-a-team.html- URL
open.deskteam360.com/dt-ad-hire?role=...(live in GHL)- Who it is for
- Business owners about to hire a designer, developer or video editor.
- They searched
- hire graphic designer, hire video editor, hire web developer, hire wordpress developer, hire gohighlevel expert, hire clickfunnels expert, hire landing page designer
- Main message
- A whole team, not one employee. No job posts, no interviews, no training. One 30-minute call.
- Proof on page
- Same numbers as page 1. One hire vs team table (US median web developer pay $92,650, BLS). Quotes: Women In White Coats, Fit Tribe Gym, FitBodies4Life, Lemonade Legend, Convert on Command.
- Offer line
- From $1,497/mo, no contracts, 30-day full refund
- Button text
- "Book your hiring call"
- Tracking value
lp_variant = bi1_hire_team, plusrolefrom the URL
Files: download both (zip) · preview BI-1 · preview BI-4. BI = Big Idea, the main message of the ad group and its page.
Page 2 changes its words by the ?role= in the URL
Each BI-1 ad points to the page with a role value, so the headline chip, subheadline and services grid name the role the person searched. Without role, the page shows the general version. We send role to GA4, Clarity and GHL so we can see which role books calls.
| Search intent | role value | Final URL |
|---|---|---|
| hire graphic designer | graphic-designer | https://open.deskteam360.com/dt-ad-hire?role=graphic-designer |
| hire video editor | video-editor | https://open.deskteam360.com/dt-ad-hire?role=video-editor |
| hire web developer | web-developer | https://open.deskteam360.com/dt-ad-hire?role=web-developer |
| hire wordpress developer | wordpress-developer | https://open.deskteam360.com/dt-ad-hire?role=wordpress-developer |
| hire landing page designer | landing-page-designer | https://open.deskteam360.com/dt-ad-hire?role=landing-page-designer |
| hire gohighlevel expert | gohighlevel-expert | https://open.deskteam360.com/dt-ad-hire?role=gohighlevel-expert |
| hire clickfunnels expert | clickfunnels-expert | https://open.deskteam360.com/dt-ad-hire?role=clickfunnels-expert |
What Google Ads adds to every click
Rodrigo sets this in Google Ads as the account's final URL suffix. You do not need to set it, but use the same parameters when you test, so the test looks like a real ad click.
utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_content={creative}&utm_term={keyword}&matchtype={matchtype}&device={device}&network={network}Google also adds gclid (or gbraid / wbraid on some iPhone traffic) when auto-tagging is on. That ID is what lets GHL tell Google Ads "this click booked a call".
2Create the Google Tag Manager container DeskTeam360
We use a new container only for the landing pages. It keeps the ads tracking separate from the main site and from the older container Rodrigo can see today (that one is not installed on any page).
- Go to tagmanager.google.com and sign in with the Google account that owns DeskTeam360's Google assets.
- Open the existing DeskTeam360 GTM account. If there is none, click Create Account, account name
DeskTeam360, country United States. - Click Admin → under Container, click + (Create Container).
- Container name:
DT360 - Ads Landing Pages. Target platform: Web. Click Create. - GTM shows the install code. Close it for now (you will paste it in Part 8). Write down the container ID at the top right. It looks like
GTM-XXXXXXX. - Give Rodrigo access: Admin → Container → User Management → + → Add users. Email
rodrigopatria@gmail.com. Container permissions: Publish. Click Invite. - Add Rodrigo's DeskTeam360 reporting email with container permission Read:
dt360-reporting@deskteam360-reporting.iam.gserviceaccount.com. It is a read-only robot account that only Rodrigo's DeskTeam360 reports use. It lets him check the container setup automatically and cannot change anything.
3Microsoft Clarity DeskTeam360
Clarity is free. It records how people scroll and click on the page, so we can see where they stop. One note: Clarity cannot see inside the GHL calendar, because the calendar is a separate site inside an iframe. It sees the page around it, and we send it a booked_call event so we can filter the recordings of people who booked.
3.1 Create the project
- Go to clarity.microsoft.com and sign in with a company account (Google or Microsoft). Use a DeskTeam360 account, not a personal one, so the project stays with the company.
- Click + New project. Name:
DeskTeam360 - Ads Landing Pages. Website URL:https://open.deskteam360.com. Click Add new project. - On the install screen, choose Install manually. Do not paste the code in the page. We install it with GTM in Part 7.
- Copy the project ID. It is the short code at the end of the script, in
"script", "abcd1234ef". You can also find it later in Settings → Overview.
3.2 Give Rodrigo access
- Open the project → Settings → Team → Add team member.
- Email
rodrigopatria@gmail.com, role Admin. Click Add.
3.3 Settings
- Settings → Setup → Google Analytics integration → Get started → connect GA4 property DeskTeam360.com - GA4 (property ID
398633583). This adds a Clarity recording link to GA4 data. - Settings → Masking → keep Balanced (the default).
- Settings → IP blocking → add the public IP address(es) of the DeskTeam360 office so the team's own visits are not recorded. (Find the office IP by searching "what is my IP" on Google from an office computer.)
3.4 Create the API token for Rodrigo's reports
- Settings → Data Export → Generate new API token.
- Token name:
3HRV reporting. Click Generate. - Copy the token right away. Clarity shows it only once.
- Send it to Rodrigo with a one-time secret link (see the rules in Part 0). Do not put it in the Part 10 form or in an email.
4Google Ads conversion actions Rodrigo DeskTeam360
Account: 546-353-3699. Google tag already used by DeskTeam360: AW-799375519.
Who does what in Part 4
- Rodrigo creates both conversion actions (4.2 and 4.3) and sends you the conversion label for Part 7. You do not need to create anything in Google Ads.
- You do 4.1 (check auto-tagging) and 4.4 (link GA4). Leave every existing conversion action as it is.
Steps 4.2 and 4.3 stay here for reference.
Why only one of the two will bid
In 2023 the account told Google that page views were conversions, so Google found cheap visitors, not buyers. This time Google bids on one thing only: a booked call, counted when the thank-you page loads (browser action). The GHL action is a second count from the CRM, so it must be Secondary. If both were Primary, every call would count twice.
4.1 Check auto-tagging
- In Google Ads, open Admin → Account settings → Auto-tagging.
- It must say Tag the URL that people click through from my ad (on). If it is off, do not change it; tell Rodrigo.
4.2 Action 1: DT360 - Booked Call (GHL) (Secondary) Rodrigo
- Goals → Conversions → Summary → + Create conversion action.
- Choose Import → CRMs, files or other data sources → Track conversions from clicks → Continue. On "Choose a data source", choose Skip this step and set up a data source later. GHL sends the data through its Google Ads connection, so no data source is needed.
- Settings:
Goal and action optimization Book appointment category · Secondary action Conversion name DT360 - Booked Call (GHL)(exact text, GHL looks for this name)Value Don't use a value Count One Click-through conversion window 30 days Attribution Data-driven - Click Save and continue → Done.
4.3 Action 2: DT360 - Booked Call (browser) (the one Google bids on) Rodrigo
- Goals → Conversions → Summary → + Create conversion action → Website.
- Enter
deskteam360.comand click Scan. Then choose Add a conversion action manually. - Settings:
Goal category Book appointment Conversion name DT360 - Booked Call (browser)Action optimization Primary action Value Don't use a value Count One Click-through window 30 days Engaged-view and view-through windows Leave default Attribution Data-driven - Click Done → Save and continue.
- On the tag setup screen, choose Use Google Tag Manager. Copy the two values Google shows:
- Conversion ID: should be
799375519. If it is a different number, tell Rodrigo. - Conversion label: a code like
AbC-D_efG-h12_34-567. Rodrigo sends it to the team for Part 7.
- Conversion ID: should be
4.4 Link Google Ads and GA4
Today GA4 is linked to three other Google Ads accounts but not to 546-353-3699. Add this link (do not remove the others).
- In GA4 (property
398633583): Admin → Product links → Google Ads links → Link. - Choose Google Ads accounts → tick 546-353-3699 → Confirm → Next.
- Keep Enable personalized advertising on and Enable auto-tagging on. Click Next → Submit.
- Do not import GA4 events into Google Ads as conversions. That would count booked calls a third time.
Rodrigo does this part (not the team)
Keep DT360 - Booked Call (browser) as the only Primary action in the goal the campaigns use, move the old page-view actions to Secondary, and set the final URL suffix. These change how Google bids, so Rodrigo does them himself.
5Google Analytics 4 DeskTeam360
Use the existing property DeskTeam360.com - GA4 (property ID 398633583, measurement ID G-ZSLFPBZD33). Do not create a new property. Pages on open.deskteam360.com share the main domain, so visitors are tracked as one user across the main site and the pages.
5.1 Data stream settings
- Admin → Data collection and modification → Data streams → open the web stream with
G-ZSLFPBZD33. - Enhanced measurement: on (page views, scrolls, outbound clicks, site search, video, file downloads).
- Configure tag settings → Show more → List unwanted referrals → add two conditions, "Referral domain contains":
leadconnectorhq.comandmsgsndr.com. Save. (Stops the calendar from showing up as a traffic source.) - Configure tag settings → Show more → Define internal traffic → Create → rule name
DT360 office,traffic_typevalueinternal, IP address equals the office IP(s). Save.
5.2 Filter and retention
- Admin → Data collection and modification → Data filters → open Internal Traffic → set it to Testing for now. Rodrigo will switch it to Active after Part 9, so your test booking is still visible.
- Admin → Data collection and modification → Data retention → Event data retention 14 months → Save.
5.3 Key event: booked_call
- Admin → Data display → Key events → New key event.
- Name:
booked_call(lowercase, exact). Save. Counting method: Once per session.
The main site code also has an event called booked_call. That is fine. Reports separate the two by hostname and by lp_variant.
5.4 Custom dimensions
Admin → Data display → Custom definitions → Create custom dimension. Create these four, all with scope Event:
| Dimension name | Scope | Event parameter | Example values |
|---|---|---|---|
| LP variant | Event | lp_variant | bi4_white_label, bi1_hire_team |
| Role | Event | role | graphic-designer, none |
| CTA text | Event | cta_text | Book your crew call |
| Booking method | Event | booking_method | ghl_iframe_message |
6GoHighLevel DeskTeam360
GHL is where a booked call really lives. The goal of this part: every booking from the ads carries its source (gclid, UTMs, page, role) and GHL tells Google Ads about it.
6.1 Custom fields
Settings → Custom Fields → + Add Field → type Single Line, object Contact. Put them in a new folder called Ads Attribution.
| Field name | Unique key GHL creates | Filled from URL parameter |
|---|---|---|
| gclid | contact.gclid | gclid |
| gbraid | contact.gbraid | gbraid |
| wbraid | contact.wbraid | wbraid |
| UTM Source | contact.utm_source | utm_source |
| UTM Medium | contact.utm_medium | utm_medium |
| UTM Campaign | contact.utm_campaign | utm_campaign |
| UTM Term | contact.utm_term | utm_term |
| UTM Content | contact.utm_content | utm_content |
| Landing Page | contact.landing_page | landing_page |
| Role | contact.role | role |
GHL makes the key from the field name. If the key it shows is different (for example contact.utm_source_1), write down the real key and send it in Part 10.
6.2 Booking form with hidden fields
- Sites → Forms → Builder. Open the form that "DeskTeam360 Demo Call 1" uses today (check in its calendar settings) and click Duplicate. If it uses the default calendar form, create a new form with the same visible fields (first name, last name, email, phone, plus any questions it asks today).
- Name the copy
DT360 - Ads Booking Form. Do not add new visible questions. The page copy and the call process stay as they are. - Drag the 10 custom fields from 6.1 into the form. For each one, open its settings: tick Hidden and set Query Key to the URL parameter in the table (for example field "UTM Source", query key
utm_source). - Save the form.
6.3 New calendar for ad traffic
- Calendars → Calendar Settings → find DeskTeam360 Demo Call 1 → three dots → Clone.
- Rename the clone
DT360 - Google Ads Call. Keep the same team members, availability, duration (30 minutes), reminders and confirmation emails. - In the calendar's Forms settings, choose custom form →
DT360 - Ads Booking Form. - In Confirmation, choose Redirect to URL:
https://open.deskteam360.com/dt-ad-booked(the thank-you page from Part 8.5). If there is an option to add contact or appointment details to the URL, leave it off: names and emails must never go into a URL, because GA4 and Clarity would record them. This redirect is why the ads calendar must be separate from the main site's calendar. - Save. Open Share / embed code and copy the calendar widget ID. It is the code after
/widget/booking/in the embed URL. Today's calendar isBvMnlvEIoMKwnPB3eQjZ; the new one will be different.
6.4 Connect Google Ads to GHL
- Settings → Integrations → Google → Connect. Sign in with a Google account that has Admin or Standard access to Google Ads 546-353-3699.
- When GHL asks which Google Ads account to use, choose 546-353-3699. If GHL only connects through Ad Manager, use Marketing → Ad Manager → Google and pick the same account.
6.5 Two workflows
GHL's Add to Google Ads action officially works only with some triggers (Form Submitted, Order Purchase, Survey, Number Pool Calling, Chat Widget). Customer Booked Appointment is not one of them. So we use two workflows: one for tags and the opportunity, one for Google Ads.
Workflow A: DT360 - Google Ads Booked Call (tags and opportunity)
Automation → Workflows → + Create Workflow → Start from scratch.
| # | Block | Settings |
|---|---|---|
| Trigger | Customer Booked Appointment | Filter: Calendar is DT360 - Google Ads Call |
| 1 | If / Else on UTM Source | Branch "Google": contact.utm_source is google → steps 2 to 4. None branch: Add tag acq:unknown-source, then end. |
| 2 | Add Contact Tag | acq:google-ads and acq-stage:booked |
| 3 | If / Else on Landing Page | Branch "BI-4": contact.landing_page contains bi4 → Add tag acq-lp:bi4. Branch "BI-1": contains bi1 → Add tag acq-lp:bi1. None branch: Add tag acq-lp:unknown. |
| 4 | Create / Update Opportunity | Pipeline Sales Pipeline, stage Appointment Scheduled, opportunity name {{contact.name}} - Google Ads, source Google Ads. Allow only one opportunity per contact in this pipeline. |
Workflow B: DT360 - Google Ads Conversion Upload (sends the booking to Google Ads)
| # | Block | Settings |
|---|---|---|
| Trigger | Form Submitted | Filter: Form is DT360 - Ads Booking Form (the calendar's form from 6.2) |
| 1 | If / Else on gclid | Branch "Has click ID": contact.gclid is not empty. None branch: end. |
| 2 | Add to Google Ads (in the "Has click ID" branch; find it in the action list by typing "Google Ads") |
Action Name: Send booked call to Google AdsConversion: DT360 - Booked Call (GHL) (pick it from the list; it appears once Rodrigo has created it and Google Ads is connected in 6.4; the list can take up to 15 minutes to fill)Currency: USD Conversion Value: leave empty (or 0) Custom Mapping: turn on and map GCLID to {{contact.gclid}}. Leave GBRAID and WBRAID empty (they only work with a different counting setting). |
Publish both workflows (toggle at the top right). In each workflow's Settings, turn Allow re-entry off.
If Workflow B does not run
A booking through the calendar should count as a submission of its form. If the test (Part 9, row 9) shows Workflow B did not start, do not try other triggers: tell Rodrigo. Google Ads still gets the booking from the browser action, which is the one that bids.
7Build the GTM container DeskTeam360
Open the container DT360 - Ads Landing Pages. Create everything below with the exact names, then publish once at the end. You need: the Clarity project ID (Part 3) and the browser conversion label (Part 4.3).
7.1 Built-in variables
Variables → Built-In Variables → Configure → tick: Page URL, Page Path, Page Hostname, Referrer, Event, Click Element, Click Classes, Click ID, Click Text, Click URL, Scroll Depth Threshold.
7.2 User-defined variables
Variables → User-Defined Variables → New.
| Name | Type | Settings |
|---|---|---|
const - GA4 ID | Constant | G-ZSLFPBZD33 |
const - Ads ID | Constant | AW-799375519 |
const - Ads Conversion ID | Constant | 799375519 |
const - Ads Label Booked Call | Constant | The label from Part 4.3 |
const - Clarity ID | Constant | The Clarity project ID from Part 3 |
DLV - lp_variant | Data Layer Variable | Name lp_variant, version 2, default value unknown |
DLV - role | Data Layer Variable | Name role, version 2, default value none |
DLV - booking_method | Data Layer Variable | Name booking_method, version 2 |
URL - gclid | URL | Component type Query, query key gclid |
7.3 Triggers
Triggers → New.
| Name | Type | Settings |
|---|---|---|
Init - All Pages | Initialization | All Initialization Events |
PV - All Pages | Page View | All Page Views |
DOM - All Pages | Page View → DOM Ready | All DOM Ready Events |
CE - booked_call | Custom Event | Event name booked_call |
Click - CTA to calendar | Click → Just Links | Some Link Clicks: Click URL contains #book |
Click - See plans | Click → Just Links | Some Link Clicks: Click URL contains #plans |
Vis - Calendar section | Element Visibility | Selection method ID, element ID book. When to fire: Once per page. Minimum percent visible: 30. Tick Observe DOM changes. |
Scroll - 25 50 75 90 | Scroll Depth | Vertical, percentages 25,50,75,90, enable on Window Load |
7.4 Tags
Tags → New. Create in this order.
Tag 1: Google Tag - GA4
- Type: Google Tag. Tag ID:
{{const - GA4 ID}}. - Configuration settings → add parameters:
lp_variant={{DLV - lp_variant}},role={{DLV - role}}. (These are then sent with every GA4 event.) - Trigger:
Init - All Pages.
Tag 2: Google Tag - Google Ads
- Type: Google Tag. Tag ID:
{{const - Ads ID}}. - Trigger:
Init - All Pages.
Tag 3: Conversion Linker
- Type: Conversion Linker. Keep defaults. Trigger:
Init - All Pages. - This saves the
gclidin a first-party cookie so Google Ads can match the conversion.
Tag 4: Clarity - Base
- Type: Custom HTML. Trigger:
Init - All Pages. Paste:
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "{{const - Clarity ID}}");
window.clarity("set", "lp_variant", "{{DLV - lp_variant}}");
window.clarity("set", "role", "{{DLV - role}}");
window.clarity("set", "has_gclid", /[?&](gclid|gbraid|wbraid)=/.test(location.search) ? "yes" : "no");
</script>Tag 5: GHL - Message Logger (debug)
- Type: Custom HTML. Trigger:
DOM - All Pages. - It does not send anything. When the page is opened with
?dt_debug=1, it prints the messages the GHL calendar sends to the browser console. It helps us fix things if the redirect to the thank-you page ever stops working. The booked call itself is counted on the thank-you page (Part 8.5).
<script>
(function () {
if (!/[?&]dt_debug=1/.test(location.search)) { return; }
var GHL_ORIGIN = /(leadconnectorhq\.com|msgsndr\.com|gohighlevel\.com|deskteam360\.com)$/i;
window.addEventListener('message', function (e) {
var host = '';
try { host = new URL(e.origin).hostname; } catch (err) { return; }
if (GHL_ORIGIN.test(host)) { console.log('[DT360 GHL message]', host, e.data); }
});
})();
</script>Tag 6: GA4 - booked_call
- Type: Google Analytics: GA4 Event. Measurement ID:
{{const - GA4 ID}}. Event name:booked_call. - Event parameters:
booking_method={{DLV - booking_method}},lp_variant={{DLV - lp_variant}},role={{DLV - role}}. - Trigger:
CE - booked_call. (The thank-you page pushes this event, see Part 8.5.)
Tag 7: Ads - Booked Call (browser)
- Type: Google Ads Conversion Tracking. Conversion ID:
{{const - Ads Conversion ID}}. Conversion label:{{const - Ads Label Booked Call}}. - Leave value, transaction ID and enhanced conversions empty.
- Trigger:
CE - booked_call.
Tag 8: Clarity - booked_call
- Type: Custom HTML. Trigger:
CE - booked_call. Paste:
<script>
if (window.clarity) {
window.clarity("event", "booked_call");
window.clarity("upgrade", "booked_call");
}
</script>Tag 9: GA4 - calendar_view
- Type: GA4 Event. Measurement ID
{{const - GA4 ID}}. Event name:calendar_view. - Trigger:
Vis - Calendar section.
Tag 10: GA4 - cta_click
- Type: GA4 Event. Event name:
cta_click. Parameters:cta_text={{Click Text}},cta_target={{Click URL}}. - Triggers:
Click - CTA to calendarandClick - See plans.
Tag 11: GA4 - scroll_depth
- Type: GA4 Event. Event name:
scroll_depth. Parameter:percent={{Scroll Depth Threshold}}. - Trigger:
Scroll - 25 50 75 90.
7.5 Publish
- Click Preview only after Part 8 (the container must be on the page). Then test as in Part 9.
- When the test passes: Submit → Version name
v1 - Ads LP tracking→ description "GA4, Ads, Clarity, GHL booking listener" → Publish.
8Build the pages in GoHighLevel DeskTeam360
Each page is its own GHL funnel on open.deskteam360.com. Pasting our HTML into Custom Code elements is fine for the page content: we checked the live BI-1 page and the design, the phone layout and the ?role= wording all work. What must be done the GHL way is everything around the content: the calendar, the thank-you page, the page settings and the tracking code.
What we found on the live BI-1 page (October 16)
- Wrong page title and description. The browser tab and link previews say "Hire Expert PPC Specialist | Paid Ads Manager for Hire" and talk about Google and Meta ads management. They look copied from another funnel. Fix in 8.4.
- The page can be indexed by Google (
index, follow). It must benoindex. Fix in 8.4. - No tracking at all. No GA4, no Google Ads tag, no GTM. The funnel's tracking code is empty. Fix in 8.6.
- The calendar is the main site's calendar (
BvMnlvEIoMKwnPB3eQjZ), pasted as code. Fix in 8.3. - Content, design, phone layout and the
?role=switch work. Keep them.
8.1 Funnels and paths
| Funnel name | Step and path | What it is | Status |
|---|---|---|---|
DT - Google - Ad1 - Hire | 1 step: /dt-ad-hire | BI-1 page | Exists. Fix as below. |
DT - Google - Ad4 - White Label | 1 step: /dt-ad-white-label | BI-4 page | Create. Build it the same way as Ad1. |
DT - Google - Booked | 1 step: /dt-ad-booked | Thank-you page for both | Create (8.5). |
All three on the domain open.deskteam360.com (Funnel → Settings → Domain). To create the BI-4 funnel, the fastest way is Sites → Funnels → DT - Google - Ad1 - Hire → three dots → Clone, rename it, change the path, then replace the content blocks with the BI-4 HTML.
8.2 Page content: Custom Code is OK, with these rules
- Keep the block that holds the page's
<style>CSS as the first block on the page. If it is deleted or moved below, the whole page loses its design. - Keep the BI-1 block with the
?role=script. It changes the headline chip, subheadline and services by role. After any edit, open/dt-ad-hire?role=video-editorand check the chip says "Looking to hire a video editor?". - Text changes are made in the HTML of the block. Do not add GHL headline or button elements between the code blocks; they will not match the design.
- Do not remove
id="book"from the calendar section heading. Every "Book your ... call" button scrolls to it. - Check the page on a phone after every change (GHL editor → mobile view, and on a real phone).
8.3 Calendar: use GHL's own Calendar element
In our HTML, the calendar section looks like this. Only the part marked DELETE goes away.
<section class="book" id="book"> <-- KEEP
<div class="wrap center"> <-- KEEP
<span class="eyebrow">Book your hiring call</span> <-- KEEP
<h2>Hire your team in 30 minutes.</h2> <-- KEEP
<p class="lead">Pick a time below...</p> <-- KEEP
<div class="call-list">...</div> <-- KEEP
<div class="book-box"> <-- DELETE from here
<iframe src="https://api.leadconnectorhq.com/widget/booking/BvMnlvEIoMKwnPB3eQjZ" ...></iframe>
</div> <-- DELETE to here
</div> <-- KEEP
</section> <-- KEEP
<script src="https://link.msgsndr.com/js/form_embed.js" ...></script> <-- DELETE (usually near the end of the page, maybe in another block)- In the GHL page editor, open the Custom Code block with the calendar section. Delete the
<div class="book-box">...</div>lines shown above (3 lines). Save the block. - Search all Custom Code blocks for
form_embed.jsand delete that one line. The native element does not need it. - Right under the block with the calendar section, add a new GHL Section → one Row with one column → + Add Element → Form → Calendar.
- In the Calendar element settings, choose the calendar
DT360 - Google Ads Call(Part 6.3). - Style so it continues the section above: Section background #11104C (navy), padding top 0 and bottom 40px. Row max width 1000px, centered. Calendar element background white, corner radius 22px, inner padding 10px. (Same look as the old white box.)
- Check on desktop and on phone: the heading "Hire your team in 30 minutes." (BI-1) or "Meet your crew in 30 minutes." (BI-4) sits right above the white calendar box, with no gap of a different color between them.
- Click any "Book your ... call" button on the page: it must scroll down to that section.
- Do the same on the BI-4 page.
Why the native element, and how we know it works
On a GHL page, GHL's own Calendar element is part of the page, so GHL reads the ad's URL (gclid, UTMs, role) into the contact and the hidden form fields, and follows the calendar's redirect to the thank-you page in the full browser tab. A pasted iframe treats the page as an outside website. We confirm it with one test booking (Part 9, rows 4 and 7). If the hidden fields come back empty, tell Rodrigo and use the pasted calendar with the script in Part 8.7 instead. Both ways are written out, so nothing is left to guess.
8.4 Page settings: title, description, noindex
Open each funnel step → gear icon / Page settings → SEO meta data. Replace what is there with:
| Page | Title | Description |
|---|---|---|
| Ad1 Hire | Hire a Designer, Developer or Video Editor in One Call | DeskTeam360 | Hire graphic designers, web developers, video editors and tech VAs in one 30-minute call. A whole managed team from $1,497/mo. No contracts. 30-day full refund. |
| Ad4 White Label | White-Label Web Development for Agencies | DeskTeam360 | White-label web development and design for agencies. Your agency's pit crew: developers, designers, tech VAs and video under your brand. No contracts. 30-day full refund. |
| Booked | You're booked | DeskTeam360 | (leave empty) |
Remove any social image or keywords left over from the old PPC page. The noindex tag goes in the tracking code (8.6), because it must be in the page head.
8.5 Thank-you page: /dt-ad-booked
This page is where the booked call is counted. The calendar sends people here after they book (Part 6.3), and the code in 8.6 tells GTM "booked_call" once.
- Create the funnel
DT - Google - Bookedwith one step, path/dt-ad-booked, domainopen.deskteam360.com. - Build it with normal GHL elements, same colors as the landing pages (navy
#11104C, pink#e4277a). Content:- Headline: You're booked.
- Text: Check your email for the calendar invite. On the call we'll look at what's on your list and show you who would work on it. Bring your backlog: the pages, funnels, designs or videos you need done.
- No buttons, no forms, no other calendar. Do not show the person's name or email on the page.
- Put this funnel's tracking code from 8.6 (the "thank-you" version).
8.6 Tracking code for each funnel
In each funnel: Settings → Tracking Code. There are two boxes, Head and Body. Replace GTM-XXXXXXX with the container ID from Part 2. The only difference between the landing funnels is the LP value.
<meta name="robots" content="noindex">
<script>
(function () {
var LP = 'bi1_hire_team'; // Ad4 funnel: 'bi4_white_label'
var role = (new URLSearchParams(location.search).get('role') || 'none').toLowerCase();
try { sessionStorage.setItem('dt360_lp', LP); sessionStorage.setItem('dt360_role', role); } catch (e) {}
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ lp_variant: LP, role: role, page_type: 'ads_landing_page' });
})();
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager --><meta name="robots" content="noindex">
<script>
(function () {
var lp = 'unknown', role = 'none', seen = false;
try {
lp = sessionStorage.getItem('dt360_lp') || 'unknown';
role = sessionStorage.getItem('dt360_role') || 'none';
seen = sessionStorage.getItem('dt360_booked') === '1';
sessionStorage.setItem('dt360_booked', '1');
} catch (e) {}
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ lp_variant: lp, role: role, page_type: 'ads_thank_you' });
// Count the booking once per browser session, even if the page is refreshed.
if (!seen) { window.dataLayer.push({ event: 'booked_call', booking_method: 'thank_you_page' }); }
})();
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager --><!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->Do not paste GA4, Google Ads, Clarity or Meta codes directly into GHL. They all load through GTM, so each one loads once.
8.7 Fallback only: pasted calendar with the click-data script
Use this only if Rodrigo asks for it after the Part 9 test (when the native Calendar element does not fill the hidden fields). It replaces the native element with the pasted iframe and passes the ad data into it, keeping it for 90 days for people who come back later. Replace NEW_CALENDAR_ID in three places and set LP per page.
<iframe data-src="https://api.leadconnectorhq.com/widget/booking/NEW_CALENDAR_ID" style="width:100%;border:none;overflow:hidden;" scrolling="no" id="NEW_CALENDAR_ID_dt360" title="Book your call" allow="payment"></iframe>
<script>
(function () {
var LP = 'bi1_hire_team'; // Ad4 page: 'bi4_white_label'
var FRAME_ID = 'NEW_CALENDAR_ID_dt360';
var KEYS = ['gclid','gbraid','wbraid','utm_source','utm_medium','utm_campaign','utm_term','utm_content','role'];
var STORE = 'dt360_attr';
var DAYS = 90;
var frame = document.getElementById(FRAME_ID);
if (!frame) { return; }
var base = frame.getAttribute('data-src') || frame.getAttribute('src');
var now = new URLSearchParams(location.search);
var saved = {};
try { saved = JSON.parse(localStorage.getItem(STORE) || '{}'); } catch (e) { saved = {}; }
// A new ad click replaces the saved values. Without one, use saved values younger than 90 days.
var fresh = KEYS.some(function (k) { return now.get(k); });
var data = {};
if (fresh) {
KEYS.forEach(function (k) { if (now.get(k)) { data[k] = now.get(k); } });
data._t = Date.now();
try { localStorage.setItem(STORE, JSON.stringify(data)); } catch (e) {}
} else if (saved._t && Date.now() - saved._t < DAYS * 864e5) {
data = saved;
}
var out = new URLSearchParams();
KEYS.forEach(function (k) { if (data[k]) { out.set(k, data[k]); } });
out.set('landing_page', LP);
frame.setAttribute('src', base + (base.indexOf('?') > -1 ? '&' : '?') + out.toString());
})();
</script>
<script src="https://link.msgsndr.com/js/form_embed.js" type="text/javascript"></script>8.8 Publish
- Save and publish all three funnels.
- Open each URL in a private window. Check: the tab title is the new one, the calendar shows times, and on BI-1
?role=video-editorchanges the chip. - Right-click → View page source → search for
noindexandGTM-. Both must be there.
9Test everything DeskTeam360
Do this once per page. It takes about 20 minutes per page. Take a screenshot at each check; you send them in Part 10.
9.1 Test URLs
Replace the date in gclid with today's date so each test is unique.
https://open.deskteam360.com/dt-ad-white-label?dt_debug=1&gclid=TEST_DT360_BI4_20261016&utm_source=google&utm_medium=cpc&utm_campaign=test&utm_term=white%20label%20web%20development&utm_content=testhttps://open.deskteam360.com/dt-ad-hire?role=video-editor&dt_debug=1&gclid=TEST_DT360_BI1_20261016&utm_source=google&utm_medium=cpc&utm_campaign=test&utm_term=hire%20video%20editor&utm_content=test9.2 Run the test
- In GTM, click Preview, paste the test URL, click Connect. A new tab opens with the page. Keep Tag Assistant connected when the browser moves to the thank-you page.
- In that tab, open the browser console (F12 on Windows, Cmd + Option + J on Mac, in Chrome).
- In GA4, open Admin → Data display → DebugView in another tab.
- On the page: scroll to the bottom, click one "Book your ... call" button, then book a call in the calendar. Name
TEST DT360, your+dt360testemail, a real phone if the form needs one. - Check each row below.
- Cancel the test appointment in GHL afterwards, and add the tag
testto the contact.
| # | Where to look | What you should see | If not |
|---|---|---|---|
| 1 | GTM Tag Assistant, first event | Fired: Google Tag - GA4, Google Tag - Google Ads, Conversion Linker, Clarity - Base | Check the funnel tracking code in Part 8.6 and the GTM ID |
| 2 | Tag Assistant, Variables tab | DLV - lp_variant = the page value; on page 2, DLV - role = video-editor | The data layer script must be above the GTM code |
| 3 | Tag Assistant after scrolling | GA4 - calendar_view fired once; GA4 - scroll_depth fired; after the button click, GA4 - cta_click | Check the trigger settings in 7.3 |
| 4 | The browser after booking | The whole tab goes to open.deskteam360.com/dt-ad-booked ("You're booked."). The URL has no name or email in it | If the thank-you page opens inside the calendar box, or nothing happens: copy the [DT360 GHL message] lines from the console and send them to Rodrigo |
| 5 | Tag Assistant after booking | On the thank-you page: event booked_call appears once, with lp_variant = the page you came from. Fired: GA4 - booked_call, Ads - Booked Call (browser), Clarity - booked_call. Refresh the page: it must not fire again | Check the thank-you head code (8.6) and trigger CE - booked_call |
| 6 | GA4 DebugView | booked_call with lp_variant and role parameters | DebugView can take 1 minute |
| 7 | GHL → the test contact → custom fields | gclid = TEST_DT360_..., UTM fields filled, landing_page = page value, role (page 2) | Check the hidden fields' query keys (6.2). If they are still empty, tell Rodrigo (fallback 8.7) |
| 8 | GHL → the test contact → tags and opportunity | Tags acq:google-ads, acq-stage:booked, acq-lp:bi4 or acq-lp:bi1. Opportunity in Sales Pipeline, Appointment Scheduled | Check the workflow trigger filter (6.5) |
| 9 | GHL → Workflow B → Execution logs | Workflow B started. The Add to Google Ads step shows Skipped or an error about the click ID | Expected with a fake gclid. Rodrigo tests the real upload with a real ad click. If Workflow B did not start at all, tell Rodrigo |
| 10 | Clarity → Recordings (can take up to 2 hours) | The test session, with filter Custom tags lp_variant and Smart event booked_call | Wait 2 hours, then check the Clarity ID constant |
10Send back to Rodrigo Required
Fill in this form, click Copy my answers and paste the text into an email to rodrigopatria@gmail.com with the subject "DT360 tracking setup done". Attach the screenshots from Part 9. Do not put the Clarity API token here; send it with a secret link.
AAll names in one place
| Thing | Name or value |
|---|---|
| GTM container | DT360 - Ads Landing Pages |
| GA4 property / measurement ID | 398633583 / G-ZSLFPBZD33 |
| Google Ads account / tag | 546-353-3699 / AW-799375519 |
| Google Ads conversion (bids, Primary) | DT360 - Booked Call (browser) |
| Google Ads conversion (check, Secondary) | DT360 - Booked Call (GHL) |
| Clarity project | DeskTeam360 - Ads Landing Pages |
| GHL funnels and paths | DT - Google - Ad1 - Hire /dt-ad-hire, DT - Google - Ad4 - White Label /dt-ad-white-label, DT - Google - Booked /dt-ad-booked (all on open.deskteam360.com) |
| GHL calendar / form / workflows | DT360 - Google Ads Call / DT360 - Ads Booking Form / DT360 - Google Ads Booked Call (A) and DT360 - Google Ads Conversion Upload (B) |
| GHL tags | acq:google-ads, acq:unknown-source, acq-stage:booked, acq-lp:bi4, acq-lp:bi1, acq-lp:unknown, test |
| GA4 events | booked_call (key event), calendar_view, cta_click, scroll_depth |
| GA4 parameters | lp_variant, role, cta_text, cta_target, booking_method, percent |
lp_variant values | bi4_white_label, bi1_hire_team |
role values | graphic-designer, video-editor, web-developer, wordpress-developer, landing-page-designer, gohighlevel-expert, clickfunnels-expert, none |
| Clarity tags and event | tags lp_variant, role, has_gclid; event booked_call |
| Test contact | Name TEST DT360, email with +dt360test, tag test |
BLater, not now
These are planned, but they wait until the first bookings come in and Rodrigo confirms the process. Do not build them in this round.
- Call held and no-show. When the person who runs the call marks the appointment as Showed or No-show in GHL, a workflow moves the opportunity and sends
DT360 - Call Heldto Google Ads (Secondary). Needs: who marks the status, every time. - New client. When a booked lead pays on portal.deskteam360.com, send
DT360 - New Clientto Google Ads with the plan value. Needs: a way to match portal payments to GHL contacts. - Enhanced conversions for leads (hashed email from GHL), to match bookings when the click ID is missing.
- Meta and LinkedIn tags on the pages, once we know which of the three Meta pixels on the main site is the right one.
- Consent banner. The ads target the US and Canada. Quebec privacy law may require consent for tracking; that is a legal decision for DeskTeam360.
Prepared by Rodrigo Andrade, 3HRV, for DeskTeam360. Version 3, October 19, 2026. Questions: rodrigopatria@gmail.com.