
September 2, 2025
Track Calendly with Google Tag Manager and GA4
Updated: September 2nd, 2025
If you landed on this page, you (most likely) have embedded a Calendly calendar on your website. People land on your website, they can schedule appointments, and you would like to see that data in your analytics (e.g., Google Analytics 4).
If my guess was correct, you have come to the right place. In this blog post, I will explain how to track Calendly with Google Tag Manager, and then we will send data to Google Analytics 4 as events.

Table of contents
– Hide table of contents –
- Before we continue
- What kind of interactions can we track?
- Listener code
- Custom event trigger and Data Layer Variable
- Create a Google Analytics 4 tag
- Let’s test
- Troubleshooting
- Mark calendar_event_scheduled as a key event (optional)
- Final words
Before we continue
In this blog post, I presume you have at least some basic knowledge about Google Tag Manager. If not, then read this tutorial first. And if you want to become a power GTM user, take a look at my courses.
Video tutorial
If you prefer video content, here’s a tutorial from my Youtube channel.
Google Tag Manager template
I also prepared a Google Tag Manager container template (a.k.a. recipe) to save you some time. You can download it here.
What kind of interactions can we track?
You will be able to capture the following events:
#1. When the profile page is viewed (meaning that someone lands on a page where your calendly calendar is embedded and loaded)
#2. When someone views an event type in your embedded calendar. For example, by clicking this one:
#3. When someone selects a date and time
#4. When someone schedules an event
Note: the solution that I explain in this blog post will not give you more granular data (like what exact time/date was selected or what kind of event type was viewed/scheduled). I know it would be nice to have more data, but that’s just what the official documentation of Calendly offers.
This method is good for general tracking (to know whether visitors look and schedule any events in your calendar).
By tracking all four of these distinct events, you are not just measuring the final booking; you are mapping the entire user journey through your scheduling process. This allows you to build a funnel report in Google Analytics 4 to answer important questions. For example, you can see if many users view an event type but then abandon the process before selecting a date and time. This kind of insight can help you identify potential friction points in your booking flow.
Listener code
To start tracking Calendly with Google Tag Manager, you must create a Custom HTML tag in your GTM container. Go to Tags > New > Custom HTML and paste the following code:
<script> window.dataLayer = window.dataLayer ||[]; window.addEventListener('message', function(e) { if (e.data.event && e.data.event.indexOf('calendly') === 0) { window.dataLayer.push({ 'event' : 'calendly', 'calendly_event' : e.data.event.split('.')[1] }); } } ); </script>
The reason we need this special listener code is that the embedded Calendly widget is technically a webpage living inside of your webpage, a concept known as an iframe. Because it is in its own container, standard Google Tag Manager triggers cannot easily see what happens inside it. This script acts as a bridge that is specifically designed to listen for the confirmation messages that the Calendly iframe sends out to the main page whenever a key action occurs.
This code is a listener that will be looking for Calendly events on a page (that are dispatched by the embedded calendar) and then will make them available in the Data Layer. It will push one of four events:
- profile_page_viewed – when the profile page was viewed
- event_type_viewed – when event type page was viewed
- date_and_time_selected – when the invitee selected the date and time
- event_scheduled – when the invitee successfully booked a meeting
In the triggering section of a tag, click anywhere and select the All Pages trigger. If your Calendly calendar is available only on certain pages, then you could create a more precise Pageview trigger where the condition is Page URL contains XXXX (replace XXX with the URL of the page where the calendar is embedded).
Save the tag. It’s time to test whether this listener is working. Click the Preview button in the top right corner of the Google Tag Manager interface.
Then enter the URL of the page where you have embedded a Calendly calendar.
Click connect. This will activate the preview and debug mode and will open another tab/window with your website. In it, you might see this warning.
Ignore it and don’t click “enable” on it.
Do not be alarmed by the “Unknown domain” warning for calendly.com. This message appears because the embedded Calendly widget is technically a small, separate webpage (an iframe) running inside your own site. While GTM’s Preview mode offers to connect to that inner page for debugging, we do not need it to. Our listener code is specifically designed to catch the messages that the Calendly iframe sends out to the main page. All the data we need will be captured correctly on your website’s domain.
Now, interact with that embedded calendar on your website, and schedule an event.
Go back to the GTM preview mode’s tab, and on the left side, you should see calendly events. Click one of them, expand the API call, and you should see something like this:
If you see events, that’s great. In my screenshot, there are four events for every type of interaction with the calendar:
- profile page view (a.k.a. Calendly widget was loaded)
- event type selection
- choosing date and time
- scheduling the event
If you see the events in the preview mode, too, let’s move to the next step. If you cannot, then try closing and refreshing the preview mode again. Also, check your configuration. Maybe you accidentally left some mistakes.

Custom event trigger and Data Layer Variable
Later in this blog post, we will create a Google Analytics 4 event tag to send the data to GA. But we need to define when that data should be sent.
In our case, that is when the ‘calendly‘ event is visible in the preview mode. To do that, we have to create a Custom Event trigger. In Google Tag Manager, go to Triggers > New > Custom Event and enter the following configuration.
Then let’s create a data layer variable to let us know what event happened. Was it profile_page_viewed or event_scheduled? Or maybe something else?
Go to Variables > New > Data Layer variable and enter the following settings:
I entered “calendly_event” because that is the parameter’s name that is pushed to the data layer.
Create a Google Analytics 4 tag
In this blog post, I presume that you already have the GA4 configuration tag in your container, and you know what it does. If you don’t, read this tutorial first.
Now, the time has come to send Calendly events to Google Analytics 4. In Google Tag Manager, go to Tags > New > Google Analytics > GA4 event tag.
Enter measurement ID.
Names could be calendar_profile_page_viewed or calendar_event_scheduled. Having unique event names is convenient for analysis like Path exploration. Also, in the list of events, you can clearly and quickly see what kind of calendar event it was.
If this naming convention works for you, your Ga4 event tag could look like this:
In the triggering section of the GA4 event tag, click anywhere and then select the custom event trigger you have just created. The final configuration of the tag can look like this:
Let’s test
Save the tag, and click the preview button in the GTM interface (to refresh the preview mode). The page with the embedded calendar will reload.
Note: remember that warning in the preview mode about enabling debugging for calendly.com domain? This might cause some inconvenience while you test the setup. If you try to refresh the preview mode in GTM, it will then try to connect to the calendly.com domain (instead of your website’s domain). If you face this issue, close the GTM preview tab and your website’s tab. Then click the Preview button in the GTM interface once again to restart the preview mode.
Interact with that calendar and schedule an event.
Now, go back to the Preview mode’s tab and check if you see all those calendly events. If yes, click them one by one, and you’ll see that your GA4 tag fired.
Now, go to your Google Analytics 4 property > Admin > DebugView.
Find your device in the top-left corner.
Then, in the event stream, you will see your calendar events.
Click those events to inspect what kind of data they contain. All good? Then, hit the Submit button in your GTM interface and publish a new version of the container. Calendly tracking with Google Tag Manager has just gone live!
If GA4 debug view is not working for you, take a look here.
Troubleshooting
Here are some common troubleshooting scenarios in case your setup is not working.
#1. The listener doesn’t seem to work. It fires, but you don’t see the calendly events in the GTM preview mode. In that case, try firing the listener tag later (e.g., on Window Loaded). Also, check the browser’s JavaScript console – maybe there are some calendly or Google Tag Manager errors displayed there?
#2. calendly events are seen in the preview mode, but the tag does not fire. It’s possible that your trigger contains a typo, or maybe built-in consent checks are preventing the tag from firing? These and many other reasons are explained in this guide.
Mark calendar_event_scheduled as a key event (optional)
If we look at all Calendly events that this listener tracks, one event is more important than others. That’s calendar_event_scheduled. It’s the end goal that you want your visitors to complete when they start interacting with the calendar.
Naturally, you should tell Google Analytics that this event matters more. To do that, you should mark it as “Key event” (previously known as Conversion).
While tracking all interactions is useful for behavioral analysis, marking calendar_event_scheduled as a key event elevates its importance within your reports. This tells Google Analytics that this specific action is a primary business objective. Doing so makes it easier to analyze attribution, as key events are featured more prominently in reports like the Traffic Acquisition report. It helps you quickly see which marketing channels are not just driving clicks, but are successfully driving actual bookings for your business.
To do that, go to Google Analytics admin > Key events.
Click New Key Event, enter calendar_event_scheduled and hit Save.
After you do this (and you publish the GTM container), wait 24-48 hours. Then, you will be able to see this key event data in reports such as Traffic Acquisition.
Track Calendly with Google Tag Manager: Final words
In this blog post, you have learned how to track embedded Calendly with Google Tag Manager and send those events to Google Analytics 4.
The process looks like this:
- Create a Custom HTML tag with the listener code. Fire the tag on pages where the Calendly calendar is embedded
- Create a Data Layer Variable and a Custom Event trigger
- Create a Google Analytics 4 event tag that sends the data to Google Analytics
- Don’t forget to test everything with the GA4 DebugView

55 COMMENTS
Hi Julius
I use Calendly on one of my site and track the conversions using Calendly's Analytics integration.
This integration is very easy to use, but is very annoying that all conversions are now listed as coming from referral=Calendly, no matter if the user landed on the page via cpc, organic or any other source.
Will the method you describe here solve that issue?
In other words, the booking made in calendly by a user coming from google ads will be attributed by Analytics to Ads (and not Calendly) ?
Yes, this method will solve your problem.
Hi Jorge,
I am also facing the same issue. Tried another method but it didn't work.
Can you confirm if it is working as you wanted?
So, say a Google Ads user clicks an ad and lands on mysite.com and then goes to mysite.com/booking, where there is an embedded calendly calendar. The user books a meeting , and through the magic of GTM (and your awesome listener code) that booking will be attributed to google/cpc?
If nothing else on your site breaks something, yes, the conversion will be attributed to google/cpc (because conversion is tracked on *your website* and the visitor is not redirected anywhere else.
Hi Julius,
thank you so much for this great help! But I have the same problem as Taissir, the implementation doesn´t work. Do you have any updates on this? I´ve been digging for another solution, but can´t find any. It would be fantastis if you could have another look into it and help us out here :-)
Thank you so much and all the best
Jonas
I just checked this on one demo site and everything works fine. What is the URL of the site?
Thanks for your quick response - the URL is https://seedtrace.org.
I´m at the stage to use the preview mode, but there are no events shown from calendly. Even though the cHTML calendly listener tag fired.
When I click book demo, I am just redirected to the Calendly page. Where can I see an embedded calendly calendar on your website?
To be clear, this only works when the calendly form is embedded, rather than when we click through to the calendar, correct?
Of course. This is mentioned multiple times in the blogs post including the very first sentence od the blog post.
Is there a specific reason that GA4 is needed for this to work? Can GUA also work for sites with older environments that aren't able to migrate over to GA4?
Feel free to use UA
Hi Julius,
I followed the instructions step by step, but for some reason the calendly custom event only works once (only when dlv-calendly_event = profile_page_viewed).
What could be happening? I would greatly appreciate your help.
Thanks in advance
* I have a calendly as an iframe on the website: https://www.getontop.com/booking/
I Julius!
[Problem Solved]
I had been running a customization with google optimize: it consisted of diamically changing the url of the iframe based on geographic location.
I had to exclude the page /booking from the customization. In Google Tag Manager I added an exclusion trigger (page path /booking) to the Google Optimize tag. So the listener code worked correctly for me and everything is fine.
* Any ideas on how to avoid this problem with Google Optimize in the future?
Thanks for your great content!!
Hi Julius,
Thanks a lot for this really useful post. I managed to set this up and running. I want to use the triggers in GTM server side. How can I go about it? Your help is really appreciated.
You start here https://www.analyticsmania.com/post/introduction-to-google-tag-manager-server-side-tagging/ and if you want to learn even more, you should enroll here https://www.analyticsmania.com/courses/intermediate-google-tag-manager-course/
Great article. I was wondering where did you get the HTML script from? From Calendly docs or created by yourself?
Works very well. Thanks a lot.
A mix of both
Would this work on an embeded outreach.io calendar?
No
Hi! Does this method still work if the Calendly form isn't embedded, but redirected to?
I have 4 Google Conversion action for 4 different forms, how can I get unque id for each from to differentiate like we do with hubspot listener?
I want to specifically track when an event is scheduled.
Would I edit the Data layer variable Name to this?
"calendly_event: "event_scheduled""
Or could I remove the other 3 events the listener is checking for?
I have the same question as Andrew from June 1 - I only want to track when an event is scheduled. What's the best way to do this?
Narrow down your custom event trigger to fire only on event_scheduled
Thanks for your response!
This seems to be working but I want to make sure I'm following correctly/maybe Marcie can test too.
In the custom trigger, I left "Event name" as calendly and then
- set "this trigger fires on" to "Some custom events"
- Chose dlv - calendly_event
- Selected contains
- Selected event_scheduled
Appears to be working but fleshing out!
Narrowing the trigger to only fire on "event_scheduled" isn't working for me. I set it up exactly as Andrew described, and it's not working. It works fine when set-up as described in the article, but it fires on profile_page_viewed as well as event_scheduled. Not sure what I'm doing wrong; I'll leave it to fire on both for now, but if you have any insight on the issue, please lmk!
If Calendly is not embedded is Calendly integration with GA4 enough, or is there still a need for tracking it using GTM?
Hi Julius! Great guide. I have used it for GA4 for over a year, and it works perfectly! Do you maybe have a guide or advice on how we could implement this as a Google Ads conversion inside GTM? Thank you for your precious help.
Hi Julius - i've used this with no problems on WordPress and Squarespace, but having issues implementing on Wix. I have experimented with having the cHTML fire on container load, Pageview, and History Change due to the different way Wix tracks things, but I can't seem to get the listener to pick up events no matter what I do. Any ideas / corrections would be appreciated! Thank you for all your great content!
To clarify - the cHTML tag will fire in Preview & Debug, but the calendly events do not come into the data layer. Thank you!
I too had this same issue. Please advise when you can. Thanks!
Yep, Calendly listener doesn't work on the Wix website for me either. Can't get the custom Calendly events fired. I have embedded the Calendly on the Wix website. I used this method on WordPress websites and it worked, but not on a Wix website.
There is an option to connect your Calendly to GA4 but you need to have a Professional, Teams, or Enterprise Calendly Plan.
Thank you for this great tutorial, worked for one of my clients; however, I was trying to do the same but it is not working.
I have to say that Calendly is not embedded in the website, the way it was setup is that when someone hits the button Pick a meeting time you get redirected to calendly.com/pgraves... URL - is there a way to track these events as it is set up?
Calendly has a GA4 integration built in that generates ga4 events similar to what your listener appears to do, but I've noticed that it doesn't properly attribute the correct traffic source to the resulting events/conversions. It produces a lot of self-referrals and when I then told GA4 to ignore self-referrals, it appear to all be direct sources.
Will using this GTM listener allow the proper traffic source to be identified?
@Ken Lentz - we had this issue with the native integration on https://growthmethod.com/, I've just switched over to this implementation from Julius and it's working perfectly with correct attribution.
Hi guys, I was wondering how can I set this up by using different meeting widget embed (not Calendly)?
Can I do this using a free calendly plan or do I need to upgrade to pro?
When I wrote this blog post, I was using a free plan
Any tutorial for google calendar tracking via Google Tag manager. Basically Google Calendar is embedded on the website and want to track its events.
you can't track google calendar
Hi Julius,
U know if exist a similar solution for Google appointments?
Thank you in advance
I don't know. My guess is no.
Hi Julius,
If I have my calendly embed on more than one URL (ie. mysite.com/demo and mysite.com/calendar) can I update my trigger to fire on both of those instances? Or will that make the trigger so that the URL has to show both demo and calendar in the same URL? I just want it to fire on either/or URL. Thanks!
Hello Julius,
Can I enable advanced Google conversion tracking with Calendly?
To retrieve email addresses, number?
I plan to make a CRM connection
This is great. As a QQ: Does that mean we won't need to setup GA4 in the Calendly integration, since we're using this listener to create our own GA events. Is that right?
Awesome script. Made an adjustment in the script extracting the event uri en event invitee:
<script>
window.dataLayer = window.dataLayer || [];
window.addEventListener('message', function(e) {
// Check if the message is from Calendly and contains the expected structure
if (e.origin === "https://calendly.com" && e.data.event && e.data.event.indexOf('calendly') === 0) {
// Extract the calendly event type
var calendlyEvent = e.data.event.split('.')[1];
// Initialize variables for eventUri and inviteeUri in case they're included in the message data
var eventUri = null;
var inviteeUri = null;
// Check if the message contains payload with event and invitee URIs
if (e.data.payload) {
eventUri = e.data.payload.event ? e.data.payload.event.uri : null;
inviteeUri = e.data.payload.invitee ? e.data.payload.invitee.uri : null;
}
// Push all extracted data to the data layer
window.dataLayer.push({
'event': 'calendly',
'calendly_event': calendlyEvent,
'eventUri': eventUri,
'inviteeUri': inviteeUri
});
}
});
</script>
I've done this so I can map no shows using GBQ data. Hope someone here finds it useful.
Hi Julius,
Thanks for this awesome guide. Do we have something similar cal.com embedded calendars ?
Thnaks for your help
Hi Julius, thanks for this guide. I'm traying to track a Calendly calendar that is embedded in a site through pipedrive, but it doesn't work. The div containing the calendar is named with calendly format, but the iframe src is pipedrive. Is there a way to make it work?
Thanks again!
Hi Julius
Thanks for this guide
Great tutorial many thanks.
I've integrated Google Ads tracking using the Google ads tag instead of GA4. Seems to work ok
OK, so I'm not sure if its working or not...?
When I test the form (in preview), everything appears in preview mode as it should, until I start clicking on dates etc to test. Then it appears that because calendly is hosted on an external website, and because that website doesn't have my tag on it the preview stops working. (Note: there is an entry on the left hand panel 'calendly' but with a line across it.)
So I don't get to see any more interactions on the preview after this point.
Does this mean it won't work in a live situation (Google ads conversion tracking) also?
Is the listener not able to track calendly because the calendar is hosted on an external website?
Thanks
Thank you for such a insightful and helpful documentation. I have a small issue to adress which I am facing . with the 4 events mentioned above I am also getting flooded with this particular event - calendly_event: "page_height", gtm.uniqueEventId: 39 and the uniqueEventId for it changes all the time. can you please help me regarding this, thanks
Hi Julius,
The method works except when the source is a browser Mobile Safari.
Are there any options to get around this problem?
Thank you