• Courses
    • Courses
    • Course bundles
  • Blog
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • Services
  • About
    • About
    • Contact
  • Login
  • Courses
    • Courses
    • Course bundles
  • Blog
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • Services
  • About
    • About
    • Contact
  • Login

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.

Subscribe and Get the Ebook - conversion tracking handbook

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.

Subscribe and Get the Ebook - conversion tracking handbook

 

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
Julius Fedorovicius
In Google Tag Manager Tips
55 COMMENTS
Jorge
  • Oct 28 2021
  • Reply

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) ?

    Julius
    • Oct 28 2021
    • Reply

    Yes, this method will solve your problem.

    Danyal
    • Jan 6 2022
    • Reply

    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?

Jorge
  • Oct 28 2021
  • Reply

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?

    Julius Fedorovicius
    • Oct 28 2021
    • Reply

    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.

Jonas
  • Dec 6 2021
  • Reply

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

    Julius Fedorovicius
    • Dec 6 2021
    • Reply

    I just checked this on one demo site and everything works fine. What is the URL of the site?

Jonas
  • Dec 6 2021
  • Reply

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.

    Julius Fedorovicius
    • Dec 6 2021
    • Reply

    When I click book demo, I am just redirected to the Calendly page. Where can I see an embedded calendly calendar on your website?

Bejamin
  • Dec 6 2021
  • Reply

To be clear, this only works when the calendly form is embedded, rather than when we click through to the calendar, correct?

    Julius
    • Dec 6 2021
    • Reply

    Of course. This is mentioned multiple times in the blogs post including the very first sentence od the blog post.

Phil
  • Dec 6 2021
  • Reply

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?

    Julius
    • Dec 7 2021
    • Reply

    Feel free to use UA

      John Contreras
      • Dec 7 2021
      • Reply

      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/

        John Contreras
        • Dec 8 2021
        • Reply

        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!!

Neha Rau
  • Feb 16 2022
  • Reply

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.

    Julius Fedorovicius
    • Feb 21 2022
    • Reply

    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/

Lance
  • Jun 3 2022
  • Reply

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.

    Julius Fedorovicius
    • Jun 3 2022
    • Reply

    A mix of both

James Russell
  • Nov 4 2022
  • Reply

Would this work on an embeded outreach.io calendar?

    Julius Fedorovicius
    • Nov 4 2022
    • Reply

    No

Haley
  • May 24 2023
  • Reply

Hi! Does this method still work if the Calendly form isn't embedded, but redirected to?

shadab
  • May 30 2023
  • Reply

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?

Andrew
  • Jun 1 2023
  • Reply

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?

Marcie
  • Jun 16 2023
  • Reply

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?

    Julius Fedorovicius
    • Jun 16 2023
    • Reply

    Narrow down your custom event trigger to fire only on event_scheduled

      Andrew
      • Jun 16 2023
      • Reply

      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!

Marcie
  • Jun 18 2023
  • Reply

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!

Lidija
  • Jul 13 2023
  • Reply

If Calendly is not embedded is Calendly integration with GA4 enough, or is there still a need for tracking it using GTM?

MD
  • Jul 19 2023
  • Reply

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.

Craig Skalko
  • Aug 12 2023
  • Reply

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!

    Craig Skalko
    • Aug 12 2023
    • Reply

    To clarify - the cHTML tag will fire in Preview & Debug, but the calendly events do not come into the data layer. Thank you!

      Jacksen Hayes
      • Sep 2 2023
      • Reply

      I too had this same issue. Please advise when you can. Thanks!

    Bojan Mareljic
    • Sep 19 2023
    • Reply

    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.

Ramses
  • Aug 26 2023
  • Reply

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?

Ken Lentz
  • Sep 8 2023
  • Reply

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?

    Stuart
    • Dec 14 2023
    • Reply

    @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.

Sherry
  • Sep 27 2023
  • Reply

Hi guys, I was wondering how can I set this up by using different meeting widget embed (not Calendly)?

Dominik
  • Sep 27 2023
  • Reply

Can I do this using a free calendly plan or do I need to upgrade to pro?

    Julius Fedorovicius
    • Sep 27 2023
    • Reply

    When I wrote this blog post, I was using a free plan

Hamza
  • Nov 14 2023
  • Reply

Any tutorial for google calendar tracking via Google Tag manager. Basically Google Calendar is embedded on the website and want to track its events.

    Julius Fedorovicius
    • Feb 14 2024
    • Reply

    you can't track google calendar

Carlos M. Díaz Honrado
  • Dec 14 2023
  • Reply

Hi Julius,

U know if exist a similar solution for Google appointments?

Thank you in advance

    Julius Fedorovicius
    • Dec 14 2023
    • Reply

    I don't know. My guess is no.

Abby A
  • Feb 14 2024
  • Reply

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!

Quentin
  • Mar 14 2024
  • Reply

Hello Julius,

Can I enable advanced Google conversion tracking with Calendly?

To retrieve email addresses, number?

I plan to make a CRM connection

Daniel A
  • Apr 26 2024
  • Reply

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?

Rick
  • Nov 1 2024
  • Reply

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.

Awais Ali
  • Nov 17 2024
  • Reply

Hi Julius,

Thanks for this awesome guide. Do we have something similar cal.com embedded calendars ?

Thnaks for your help

Lucas
  • Mar 5 2025
  • Reply

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!

Much
  • Apr 3 2025
  • Reply

Hi Julius

Thanks for this guide

Mark
  • Apr 16 2025
  • Reply

Great tutorial many thanks.

I've integrated Google Ads tracking using the Google ads tag instead of GA4. Seems to work ok

Mark
  • Apr 16 2025
  • Reply

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

Maksud
  • May 6 2025
  • Reply

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

Vladimir
  • Jul 27 2025
  • Reply

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

Leave a comment Cancel reply

Your email address will not be published. Required fields are marked *


 

Hi, I'm Julius Fedorovicius and I'm here to help you learn Google Tag Manager and Google Analytics. Join thousands of other digital marketers and digital analysts in this exciting journey. Read more
Analytics Mania
  • Google Tag Manager Courses
  • Google Tag Manager Recipes
  • Google Tag Manager Resources
  • Google Tag Manager Community
  • Login to courses
Follow Analytics Mania
  • Subscribe to newsletter
Recent Posts
  • Conversion rate in Google Analytics 4
  • Google Tag Manager Data Layer Explained
  • Cross-domain tracking in Google Analytics 4
Analytics Mania - Google Tag Manager and Google Analytics Blog | Privacy Policy
Manage Cookie Settings