Skip to Content

Calendly

Calendly is a popular scheduling tool that lets visitors book meetings directly from your website. Calendly widgets render inside iframes, which means the form fields inside the booking widget are inaccessible from the parent page.

AttributionHub addresses this with a dedicated handler that listens for calendly.event_scheduled postMessage events from the Calendly iframe. When a visitor completes a booking, AttributionHub captures the conversion along with full attribution data, giving you visibility into which marketing channels drive the most meetings.

Unlike traditional form integrations where hidden fields are pre-filled, the Calendly integration captures attribution at the moment of booking by creating a synthetic conversion event with all attribution data attached.

Prerequisites

Before you begin, make sure:

  • The AttributionHub tracking script is installed on your site (see Installation)
  • You have a Calendly account (Free, Standard, Teams, or Enterprise)
  • The Calendly embed SDK (window.Calendly) is loaded on your page (comes with all Calendly embed methods)

Step 1: Embed the Calendly Widget on Your Page

If you have not already, add a Calendly widget to your page. Calendly offers several embed options:

Inline embed:

<!-- Calendly inline widget --> <div class="calendly-inline-widget" data-url="https://calendly.com/your-username/30min" style="min-width:320px;height:700px;" ></div> <script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js" async ></script>

Popup widget:

<!-- Calendly popup widget --> <link href="https://assets.calendly.com/assets/external/widget.css" rel="stylesheet" /> <script src="https://assets.calendly.com/assets/external/widget.js" type="text/javascript" async ></script> <a href="" onclick="Calendly.initPopupWidget({url: 'https://calendly.com/your-username/30min'});return false;" >Schedule time with me</a >

Popup text:

<link href="https://assets.calendly.com/assets/external/widget.css" rel="stylesheet" /> <script src="https://assets.calendly.com/assets/external/widget.js" type="text/javascript" async ></script> <a href="" onclick="Calendly.initPopupWidget({url: 'https://calendly.com/your-username'});return false;" >Schedule a call</a >

All embed methods work with AttributionHub. The Calendly widget JavaScript (widget.js) must be loaded, as it makes window.Calendly available, which AttributionHub uses to confirm Calendly is present.

Step 2: Verify the Script Order

Make sure the AttributionHub tracking script loads on the same page as the Calendly widget. No special configuration is needed — AttributionHub automatically detects Calendly elements using these selectors:

  • .calendly-inline-widget
  • [data-calendly]
  • iframe[src*="calendly.com"]
  • .calendly-popup-widget
  • .calendly-embed

Step 3: Test the Integration

  1. Visit a page on your site that contains the Calendly widget
  2. Open your browser’s DevTools (F12) and switch to the Console tab
  3. Enable AttributionHub logging (enableLogging: true in settings) to see detection messages
  4. Complete a test booking through the Calendly widget
  5. After the booking confirms, check the Console for conversion tracking messages from AttributionHub
  6. The conversion event will include all attribution data plus Calendly-specific metadata

For a full testing walkthrough, see Verify It Works.

How It Works

The Calendly integration works differently from traditional form integrations:

  1. AttributionHub detects Calendly elements on the page and confirms the Calendly SDK (window.Calendly) is available
  2. It registers a message event listener on the window object
  3. When a visitor completes a booking, Calendly sends a calendly.event_scheduled postMessage event from its iframe to the parent page
  4. AttributionHub intercepts this message and creates a synthetic form — a hidden HTML form element populated with all attribution data from your field mapping
  5. The synthetic form is submitted to the conversion tracker with the event name calendly_booking
  6. The synthetic form is removed from the DOM after tracking is complete

Data Captured

Each Calendly conversion event includes:

FieldDescription
All field mapping fieldsYour standard attribution data (channel, source, medium, etc.)
conversion_timestampISO 8601 timestamp of when the booking was detected
conversion_urlThe page URL where the booking occurred
conversion_eventAlways set to calendly_booking
calendly_event_uriCalendly API URI for the event (e.g., for API lookups)
calendly_invitee_uriCalendly API URI for the invitee

Since the Calendly integration captures attribution at the moment of conversion (not via hidden fields), you do not need to add hidden fields to Calendly itself. Just make sure your attribution script settings include the fields you want to track:

<script> window.attrhub = { settings: { // Your standard field mapping applies to Calendly conversions too fieldMapping: { "latest.attribution.channelGroup": "ah_lt_channel", "latest.attribution.source": "ah_lt_source", "latest.attribution.medium": "ah_lt_medium", "latest.attribution.campaign": "ah_lt_campaign", "first.attribution.channelGroup": "ah_ft_channel", "first.attribution.source": "ah_ft_source", }, }, }; </script>

Connecting Attribution Data to Your CRM

Because Calendly bookings do not pass through a traditional form submission, you will typically connect attribution data to your CRM using one of these approaches:

Using Calendly’s Routing Feature

If you use Calendly’s Routing or Teams features, the attribution data captured in the conversion event can be sent to your CRM via Calendly’s integrations (Salesforce, HubSpot) or webhooks.

Using a Webhook or Integration Tool

Configure a webhook (e.g., via Zapier, Make, or a custom endpoint) to receive conversion events from AttributionHub. This webhook payload includes all attribution data associated with the Calendly booking.

Matching by Email

Match the Calendly invitee to a CRM contact using the email address provided during booking. Attach the attribution data as custom fields on the CRM contact record.

Tips

  • Multiple scheduling links — If you have different Calendly event types on different pages, each one captures the attribution data relevant to that specific page visit.
  • Popup widgets — Popup Calendly widgets work the same way as inline widgets. The postMessage event fires regardless of the embed mode.
  • SPA navigation — If your site is a single-page app, the Calendly handler listens for postMessage events globally, so it works even if the Calendly widget is loaded dynamically after page navigation.
  • Booking confirmation page — Attribution data is captured at the moment of booking, not on a confirmation page. This means you get accurate attribution even if the visitor does not reach a thank-you page.
  • Round-robin scheduling — If you use Calendly’s round-robin feature to distribute bookings across your team, the attribution data is captured identically regardless of which team member is assigned.

Troubleshooting

No conversion event fires after booking

  1. Make sure the Calendly embed SDK (widget.js) is loaded. Type window.Calendly in the browser Console — it should return an object, not undefined.
  2. Verify that calendly.event_scheduled postMessage events are being sent. In the Console, run:
    window.addEventListener("message", (e) => console.log(e.data));
    Then complete a booking and check for a message with event: "calendly.event_scheduled".
  3. Enable logging (enableLogging: true in settings) and check the Console for Calendly detection messages.

Calendly widget not detected

AttributionHub only registers the postMessage listener if it finds Calendly elements on the page and the Calendly SDK is present. Make sure at least one element matches one of the Calendly selectors (e.g., .calendly-inline-widget) and that widget.js is loaded before or around the same time as the AttributionHub script.

Attribution data is missing or incomplete

The attribution data comes from localStorage, which is populated on page load. If the visitor arrived directly on the page without any prior visit, the attribution data may show “Direct” values. This is expected behavior — it accurately reflects that the visitor’s traffic source was direct.