Guides · Calendly
Get paid-media UTMs onto every Calendly booking, then fire clean
event_scheduled conversions in Google Tag Manager — without
drowning the dataLayer in iframe noise.
Calendly sits in an iframe. That creates two separate problems marketers mix up constantly:
postMessage events (widget load, page
height, duplicates). A naïve listener can push 6–10 dataLayer hits when
you only needed three.
This guide solves both. Copy-ready ad recipes live below; the GTM section covers the listener problem discussed in r/GoogleTagManager.
Per Calendly Help, invitees keep only:
utm_sourceutm_mediumutm_campaignutm_contentutm_term
Each value must be under 255 characters. There is no native field for
gclid, fbclid, or custom click IDs — map those into
a UTM key if you need them inside Calendly exports, or keep them on the page
for Google Ads / Meta / Enhanced Conversions.
Your scheduling page must receive the five keys in the URL when someone lands from paid media. On Google Ads, that usually means a Final URL suffix (so a redirect click tracker can still own Tracking template).
Google Ads example (Final URL suffix):
utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_term={keyword}&utm_content={creative}
Landing-page query parameters do not automatically appear on the Calendly invitee. You must hand them to the embed.
data-urlFine for static sources (one embed per channel). Brittle for paid media.
<div class="calendly-inline-widget"
data-url="https://calendly.com/YOUR_LINK/30min?utm_source=google&utm_medium=cpc"
style="min-width:320px;height:630px;"></div>
Reuse one embed across campaigns. Calendly’s advanced JS embed:
function getUrlVars() {
const vars = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (_m, k, v) {
vars[k] = decodeURIComponent(v);
});
return vars;
}
const utms = getUrlVars();
Calendly.initInlineWidget({
url: 'https://calendly.com/YOUR_LINK/30min',
parentElement: document.getElementById('calendly-embed'),
utm: {
utmSource: utms.utm_source,
utmMedium: utms.utm_medium,
utmCampaign: utms.utm_campaign,
utmContent: utms.utm_content,
utmTerm: utms.utm_term,
},
});
After a test booking, open the invitee in Calendly and confirm the five UTM fields match the ad click.
Calendly posts messages from the iframe for more than bookings. A standard “Message” / custom event listener often catches widget loads, height changes and duplicates — so GA4 DebugView looks like a slot machine and conversion counts inflate.
Practitioners typically need only a small set, for example:
calendly.event_type_viewedcalendly.date_and_time_selected (optional funnel step)calendly.event_scheduled ← primary conversionpostMessage events (custom HTML or a community GTM template).dataLayer object, e.g. { event: 'calendly_event_scheduled', … }.
Do not rely on UTMs alone for Google Ads offline or enhanced
conversions — keep gclid on the page or map it into
utm_content with the
gclid recipe
when Calendly exports must carry the click ID.
event_scheduled only.