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
- Visit a page on your site that contains the Calendly widget
- Open your browser’s DevTools (F12) and switch to the Console tab
- Enable AttributionHub logging (
enableLogging: truein settings) to see detection messages - Complete a test booking through the Calendly widget
- After the booking confirms, check the Console for conversion tracking messages from AttributionHub
- 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:
- AttributionHub detects Calendly elements on the page and confirms the Calendly SDK (
window.Calendly) is available - It registers a
messageevent listener on the window object - When a visitor completes a booking, Calendly sends a
calendly.event_scheduledpostMessage event from its iframe to the parent page - AttributionHub intercepts this message and creates a synthetic form — a hidden HTML form element populated with all attribution data from your field mapping
- The synthetic form is submitted to the conversion tracker with the event name
calendly_booking - The synthetic form is removed from the DOM after tracking is complete
Data Captured
Each Calendly conversion event includes:
| Field | Description |
|---|---|
| All field mapping fields | Your standard attribution data (channel, source, medium, etc.) |
conversion_timestamp | ISO 8601 timestamp of when the booking was detected |
conversion_url | The page URL where the booking occurred |
conversion_event | Always set to calendly_booking |
calendly_event_uri | Calendly API URI for the event (e.g., for API lookups) |
calendly_invitee_uri | Calendly API URI for the invitee |
Recommended Configuration
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
- Make sure the Calendly embed SDK (
widget.js) is loaded. Typewindow.Calendlyin the browser Console — it should return an object, notundefined. - Verify that
calendly.event_scheduledpostMessage events are being sent. In the Console, run:Then complete a booking and check for a message withwindow.addEventListener("message", (e) => console.log(e.data));event: "calendly.event_scheduled". - Enable logging (
enableLogging: truein 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.