This article explains how attribution works, what events trigger attribution capture, and how to read the data so you can see which marketing channels are actually driving patients through your door.
Attribution is the answer to the question every practice owner asks: "Where did this patient actually come from?"
When someone interacts with your website, landing page, booking calendar, or chat widget, Aesthetix CRM captures a snapshot of how they got there — the URL they were on, what referred them, and any tracking parameters that were attached. We then categorize that snapshot into a clean source label like Paid Search, Paid Social, or Organic Search.
That label gets attached to the contact record. Over time, you can roll those labels up into reports to see which channels are producing the most leads, the most consults, and the most revenue.
Every contact in Aesthetix CRM stores two attribution records: First and Latest. They serve different purposes and answer different questions.
First Attribution | Latest Attribution | |
Captures | The very first interaction the contact ever had with your business | The most recent interaction the contact has had with your business |
Changes over time? | No — locked in forever after the first capture | Yes — overwritten on every new tracked interaction |
Best used for | Understanding which channels introduce new patients to your practice | Understanding which channels re-engage existing contacts and drive conversions |
A prospective patient sees an Instagram Reel about your CoolSculpting promo and taps through to your landing page. They fill out a "What Treatment Is Right for Me?" quiz.
First Attribution = Paid Social (Meta Ads)
Latest Attribution = Paid Social (Meta Ads)
Three weeks later, that same person Googles your practice name, clicks the organic result, and books a consult through your online calendar.
First Attribution = Paid Social (unchanged — this is locked in)
Latest Attribution = Organic Search (updated to the most recent interaction)
This is why both data points matter. First Attribution tells you what brought them in the door initially. Latest Attribution tells you what closed the loop.
Both First and Latest attribution live on every contact record.
From the left navigation, click Contacts.
Open any contact record.
Scroll to the Activity tab in the right-hand column.
Attribution data appears in the panel at the bottom right.
Each attribution record displays a detailed breakdown of the visitor's session. Here's what every field means:
Field | What it captures | Example |
Source | The categorized source label assigned by the rules engine |
|
Session URL | The first page the visitor landed on during the session that produced the conversion |
|
Page URL | The actual page where the form, calendar, or chat conversion happened |
|
Referrer | The website that referred the visitor (may be empty for direct traffic) |
|
Campaign | The friendly campaign name (from |
|
Campaign ID | The platform-assigned campaign ID (from |
|
Medium | The type of conversion event that captured the data |
|
Medium ID | The unique ID of the specific form, calendar, or widget that fired the event |
|
Submission ID | The unique ID of the conversion event itself |
|
UTM Source | The |
|
UTM Medium | The |
|
UTM Content | The |
|
UTM Event Source | A normalized summary label of the source signal |
|
gclid | Google Ads click ID (auto-appended to ad clicks when auto-tagging is on) |
|
fbclid | Facebook/Meta click ID (auto-appended to Meta ad clicks) |
|
msclkid | Microsoft/Bing Ads click ID |
|
dclid | Display & Video 360 / Google Display click ID |
|
fbc | Meta click cookie value (server-side tracking) |
|
fbp | Meta Pixel browser cookie value (used by Meta Conversions API) |
|
FB Event ID | Unique event ID for deduplication when sending to Meta CAPI |
|
GA Client ID | Google Analytics client cookie value |
|
User Agent | The browser and device used |
|
IP | The visitor's IP address (used for geolocation and fraud detection) |
|
Visitor ID | Unique ID assigned to each chat widget visitor (for session continuity) |
|
This is the single most important field distinction to understand, and it trips up almost everyone the first time they read attribution data.
Session URL = where the visitor first landed during that session (their entry point to your site)
Page URL = where the conversion event actually happened (the page hosting the form they submitted)
A visitor might land on /procedures/coolsculpting/ from a Google search (that's the Session URL), browse around, and finally submit a form on /contact/ (that's the Page URL). The attribution rules are evaluated against the Session URL — because the entry point is where the original UTMs, referrer, and source signals live. By the time the visitor reaches your contact page, those signals are usually gone.
This is also why the Session URL is incredibly useful on its own: even when no UTMs are involved, it tells you exactly which page on your site is doing the work of converting cold visitors into leads.
In addition to the native attribution panel on the Activity tab, Aesthetix CRM also auto-populates a set of custom contact fields with the most useful attribution values. These fields are filled in automatically by a workflow that runs on every new lead capture — so any contact created through one of your lead capture forms will have these custom fields populated alongside the native attribution data.
The native attribution data on the Activity tab is great for inspecting a single contact, but it has a few limitations:
It's not included in standard CSV exports — exports only include flat contact fields, not the nested attribution panel
It can't be used directly as merge fields in emails, SMS templates, or workflow conditions
It's not available as a column in list views or as a filter in smart lists
By copying the most-used attribution values into custom contact fields, those values become first-class contact data — exportable, filterable, mergeable, and usable in any workflow logic without needing to query the API.
Custom Contact Field | Mapped From | What It Contains |
First Attribution Session Source | First Attribution → Session Source | The source category from the first time this contact ever converted (Paid Search, Organic Search, Direct Traffic, etc.) — locked in forever after first conversion |
Last Attribution Session Source | Latest Attribution → Session Source | The source category from the most recent conversion — updates every time the contact triggers a new conversion event |
UTM Source | Latest Attribution → utmSource | The |
UTM Campaign | Latest Attribution → campaign | The campaign name from the most recent conversion |
UTM Content | Latest Attribution → utmContent | The ad content / variant identifier from the most recent conversion |
Attribution - Source URL | Latest Attribution → url | The full landing URL from the most recent conversion (with all parameters) |
Attribution - GCLID | Latest Attribution → gclid | The Google Ads click ID from the most recent conversion |
Attribution - FBCLID | Latest Attribution → fbclid | The Meta (Facebook/Instagram) click ID from the most recent conversion |
They populate at conversion time. A workflow action attached to your lead capture forms copies the values from the native attribution data into the custom fields the moment a new contact is created or updated. Existing contacts created before this workflow was set up may not have all these fields populated.
Most fields capture Latest attribution, not First. With the exception of "First Attribution Session Source," all the mapped fields use the Latest Attribution values. This means if a contact converts a second time through a different channel, most of these fields will update to reflect the new channel — only First Attribution Session Source stays locked to the original.
They're available as merge fields everywhere. You can reference these fields in email templates, SMS templates, workflow conditions, smart lists, segment filters, and CSV exports — anywhere custom contact fields are supported.
They're included in CSV exports. When you export contacts from the Contacts tab, these fields appear as columns — making it simple to pull attribution data into spreadsheets, BI tools, or external reports without API access.
This is one of the most common questions clients have when they first look at exported attribution data: "Why are the UTM fields blank for half my contacts?"
The answer is that UTM parameters and click IDs only exist on URLs that were explicitly tagged with them — typically by a paid ad campaign. They don't magically appear on every visitor's URL. Here's what gets populated for each source type:
Source Type | Source URL | UTM Source / Campaign / Content | GCLID | FBCLID | Session Source |
Paid Search (Google Ads) |
|
|
| — |
|
Paid Search (Bing Ads) |
|
| — | — |
|
Paid Social (Meta Ads) |
|
| — |
|
|
Organic Search |
|
| — | — |
|
Social Media (organic) |
|
| — | — |
|
Referrals |
|
| — | — |
|
Direct Traffic |
|
| — | — |
|
Others (call, SMS, email, DM) |
|
| — | — |
|
CRM UI / CRM Workflows / Third-Party |
|
| — | — |
|
Key takeaways from this table:
Session Source (First and Last) populates for every contact, regardless of source. This is the most reliable field for building smart lists and reports — every contact will have a value in it.
UTMs only populate for contacts who arrived through a tagged URL. That's almost always paid ads. If you want to enable UTM-based reporting on your organic posts (e.g., the link in your Instagram bio, your email newsletter links), you'll need to manually add UTM parameters to those URLs yourself — the system won't fabricate them.
GCLID and FBCLID only populate for contacts who clicked through from Google Ads or Meta Ads, respectively. These click IDs are auto-appended by the ad platforms when auto-tagging is enabled. Organic visitors will never have them.
Contacts created without a web session at all (CRM UI, CRM Workflows, Third-Party, Others) will have most attribution fields empty. Only the Source Session field will be populated.
For practical reporting: Use Last Attribution Session Source as your primary segmentation field — it works for every contact. Use UTM and click ID fields when you specifically need to drill into paid campaign performance.
Use Case | Where To Look |
Quickly seeing where a single contact came from | Native Activity tab on the contact |
Building a smart list of "all leads from Paid Search this month" | Custom field: Last Attribution Session Source |
Exporting a contact list with source data for an external report | Custom fields (included in CSV export) |
Including the original campaign name in a follow-up email | Custom field merge: UTM Campaign |
Triggering a workflow only for leads with a specific GCLID | Custom field condition: Attribution - GCLID |
Pulling rich session detail (IP, user agent, FB Event ID, click cookies, etc.) | Native attribution panel (or API) |
Building a custom dashboard or BI integration | API (see For developers and integrations) |
Need additional fields mapped? The default setup covers the most commonly-used attribution values. If you want additional fields mapped into custom contact fields (e.g., MSCLKID for Bing Ads, the campaign ID, the IP address, the FB Event ID), our team can add those to your lead capture workflows. Submit a Custom Build Request with the specific fields you'd like added.
This is one of the most common points of confusion in the platform, because there are actually two different "source" concepts on every contact, and they don't always agree.
The Contact Source is a single text value attached to every contact, set at the moment the contact is created. It typically reflects how the contact entered the system — for example, the name of the form they submitted, "Manual Entry," or "API."
You can see this field at the top of the contact record, alongside their name, email, and phone. It's what powers the Lead Source widget on the dashboard.
You can control the Contact Source value in three ways:
Set it inside the form builder. Add a hidden Source field to any form/survey and define the value (e.g., "Botox Landing Page Form"). This becomes the Contact Source for any lead that submits that form.
Override it via URL parameter. Append ?source=your_custom_value to any page URL. The submitted form will use that value instead of the form's built-in source. This is useful for tagging traffic from specific campaigns or partners with a custom label.
Let the system fill it in by default based on the form name, integration, or creation method.
How Aesthetix CRM protects Contact Source from being overwritten: In any of our standard workflows that include a Contact Source update action (lead capture workflows, re-engagement workflows, etc.), the workflow first checks whether a Contact Source already exists on the contact — and only sets the value if the field is empty. This prevents a returning lead's original source from being overwritten by a later interaction. The value you see in the Contact Source field is reliably the original source assigned at first capture, even if the contact has had many subsequent interactions.
The Attribution Source is the marketing channel categorization (Paid Search, Organic Search, Direct Traffic, etc.) that the rules engine assigns based on the URL parameters and referrer of the conversion event. It lives on the attribution panel under the Activity tab.
This is what the rest of this article has been about.
Contact Source | Attribution Source | |
Set by | The form builder, URL | The attribution rules engine (12 rules, first-match-wins) |
Format | Free-text label (any string) | One of the standardized source types (Paid Search, Direct Traffic, etc.) |
Where it lives | Top of the contact record, single field | Activity tab → Attribution panel, two records (First and Latest) |
Used for | Quick identification of "where this lead came in from" | Categorized channel reporting and attribution analysis |
Updates over time | No — set once at first capture and protected from overwrite by Aesthetix CRM workflows | Latest Attribution updates on every new conversion; First Attribution is locked |
A contact might have Contact Source = "Botox Landing Page Form" and First Attribution Source = "Paid Search" simultaneously. Both are correct — they're answering different questions. The Contact Source tells you which form they filled out; the Attribution Source tells you what marketing channel drove them to that form.
For most reporting, Attribution Source is the more useful field — because it gives you the standardized channel categorization needed to compare performance across sources. Use Contact Source when you specifically want to know which form or asset captured a lead.
Everything we've covered so far has been about reading attribution data on a single contact. To see attribution across all your contacts and roll up reporting at the channel/campaign level, use:
Attribution Report (Reporting → Attribution Report) — shows where and how leads entered your platform across selected date ranges, broken down by source, campaign, and medium
Google Ads Report (Reporting → Google Ads) — campaign, ad group, and ad-level performance for Google Ads traffic (requires Google Ads UTM template setup)
Facebook Ads Report (Reporting → Facebook Ads) — campaign, ad set, and ad-level performance for Meta Ads traffic (requires Meta UTM template setup)
Call Reports (Reporting → Call Reporting) — inbound call volume, duration, and source attribution (requires Number Pools for source-level detail)
Custom Dashboards with attribution filters — when building a custom dashboard widget on Contacts or Opportunities data, you can add Session Source, UTM Source, UTM Medium, UTM Campaign, and other attribution properties as filters and grouping dimensions to build your own attribution views
Reporting: All-In-One Guide
Learn about how all Aesthetix CRM reporting works and the limitations of reporting & dashboards in the system.
Dashboards: All-In-One Guide
Review this help article to learn everything about our template dashboards and how to build your own custom dashboard widgets.
Every contact's First and Latest attribution will be categorized as one of the following source types.
Source | What It Means | Common Scenario for a Med Spa |
Paid Search | Click came from a paid search ad (Google Ads, Microsoft/Bing Ads) | A patient searches "Botox near me," clicks your Google Ad, and books a consult |
Paid Social | Click came from a paid social ad (Meta, LinkedIn, X/Twitter, Reddit, WhatsApp click-to-chat ads) | A patient taps a sponsored Instagram post for your laser hair removal special |
Organic Search | Click came from an unpaid search engine result | A patient searches "best filler injector in [city]" and clicks your organic listing |
Social Media | Click came from an organic post, story, or share on a social platform | A patient clicks the link in your Instagram bio after seeing a Reel |
Referrals | Click came from another website that isn't a search engine or social platform | A patient clicks through from a "best med spas" blog post or a directory listing |
Direct Traffic | No referring source detected — typed the URL directly, used a bookmark, or had referrer data stripped | A returning patient types your website URL into their browser |
Others | Lead came in through a non-web channel — inbound call, SMS, email, WhatsApp, or Facebook Messenger | A patient calls your tracking number after seeing a print ad |
CRM UI | Lead was created manually inside Aesthetix CRM by a team member | Front desk adds a walk-in patient to the system by hand |
CRM Workflows | Lead was created or modified by an automated workflow inside Aesthetix CRM | A workflow auto-creates a contact based on a webhook trigger or an internal automation |
Third-Party | Lead was created by an external integration (Zapier, native API, EMR sync, etc.) | A new patient created in your EMR is synced into Aesthetix CRM via an integration |
About "CRM Workflows": This source type appears on contacts created or substantially modified by an automated workflow inside Aesthetix CRM (as opposed to manual creation, which produces "CRM UI"). It's a relatively new source type and may not be exhaustively documented in older help materials yet — if you see it on contacts in your account, this is what it means.
This is where most clients get tripped up — so it's worth walking through carefully. There are two questions to answer:
What events trigger an attribution capture? (When does the system save the data?)
What needs to be in place for that data to be complete? (How does the plumbing work?)
Aesthetix CRM does not track attribution on every page view by default. Attribution is recorded only at the moment of a conversion event that creates or updates a contact. The full list of events that trigger an attribution capture:
Web-based conversion events (rich attribution capture):
Submits a Form built in Aesthetix CRM (or a compatible HTML <form> on a page where the External Tracking Script is installed)
Submits a Survey built in Aesthetix CRM
Books an appointment through an Aesthetix CRM Calendar widget
Submits contact info through the Aesthetix CRM Chat Widget
Completes an Order Form (one-step or two-step) built in Aesthetix CRM
Clicks a Trigger Link sent in an email, SMS, WhatsApp, GMB, or Messenger/DM message
Non-web conversion events (limited attribution capture):
Inbound phone call — creates or updates a contact based on the caller's phone number. By default, calls are categorized as Others with no source detail. If the call is to a Number Pool number (Pattern D), the system matches the call back to the visitor's original web session via cookie and assigns the correct source (Paid Search, Organic Search, etc.) instead of Others.
Inbound SMS, email reply, WhatsApp message, or Facebook/Instagram DM — creates or updates a contact based on the inbound message. These are categorized as Others (for SMS/email) or Social media with minimal data (for WhatsApp/Messenger/IG DM). See Limitation #8 for details on the limited attribution data captured from messaging channels.
If none of these events occur, no contact is created and no attribution is recorded.
About Trigger Links: These are tracked redirect links you create inside Aesthetix CRM (under Conversations → Trigger Links) and use in your outbound messages. When a contact clicks one, the click is logged on their activity timeline, can fire a workflow, and updates their Latest Attribution data. This is why you'll occasionally see contacts whose Latest Attribution shows
url: "Trigger Link"in the API or attribution panel — that contact recently clicked one of your tracked links.
About Number Pool calls: A call to a Number Pool tracking number is a full conversion event. The call itself triggers contact creation/update, and the source attribution inherited from the original web session is what makes the difference between Others (no source) and a properly categorized channel attribution. Without Number Pools, the call still creates a contact — it just gets the generic Others source. See Pattern D for setup details.
Just having a form is only half the story. For attribution data to be complete and accurate — especially for visitors who browse multiple pages before converting — there needs to be a tracking mechanism present on every page of your site to capture the original session data and carry it forward.
There are three patterns for how this works in practice. Pick the one that matches your setup.
If your website, funnel, or landing page is built inside Aesthetix CRM, attribution tracking is built in automatically. The platform's JavaScript is already on every page. There's nothing to configure — UTMs, referrers, page paths, and session data flow through to the conversion event without any additional setup.
Best for: Practices that have built their main website, funnel, or specific campaign landing pages directly inside Aesthetix CRM.
If your main website is hosted on WordPress, Squarespace, Shopify, Webflow, Wix, or any other external platform, the Aesthetix CRM Chat Widget doubles as a session tracking script. As long as the chat widget code is installed on every page of your site, it does two things automatically:
Stores anonymous session data (entry URL, UTMs, referrer, click IDs) in the browser as soon as the visitor lands
Carries that session data across page navigations until the visitor finally converts — whether they convert through the chat widget itself, an embedded form, or an embedded calendar
When the conversion happens, the original session data from the entry page is attached to the contact, even if the conversion page is several clicks away from where the visitor first arrived.
Best for: Practices already using (or open to using) the Chat Widget. This is the easiest way to get cross-page attribution working without installing a separate tracking script — because the chat widget is doing the work for you.
If you don't use the Chat Widget but still need accurate cross-page attribution on an external website, install the External Tracking Script. This is a lightweight JavaScript snippet that does the same session-tracking job as the Chat Widget — without adding a chat interface to your site.
To install:
From the left navigation, go to Settings → External Tracking
Click Copy Script to grab your unique snippet
Paste it just before the closing </body> tag on every page of your external site
The script will then:
Record page views anonymously, even before a contact exists
Store session data (entry URL, UTMs, referrer, click IDs) in the visitor's browser
Attach that session data to the contact when an embedded form is finally submitted
Capture supported custom field values from compatible HTML forms
Make page-view activity available as a workflow trigger
Best for: Practices on external websites that don't use the Chat Widget, or any practice that wants the additional ability to trigger workflows from page-view activity (e.g., "if someone visits the CoolSculpting page 3 times in a week, send a follow-up sequence").
For the External Tracking Script to capture form submissions (not just page views), the form must meet these requirements:
A real <form> HTML element exists in the page DOM
An <input type="email"> field is present
All fields you want captured are visible (not display: none) and have a valid name attribute
The form is not inside an iframe
The form is not rendered by a third-party JavaScript widget that injects a <div>-based UI
Supported field types:
The script can capture and map a wide range of field types when properly configured:
Single-line and multi-line text
Dropdowns (single-select and multi-select)
Checkboxes and radio buttons
Number, monetary, and date picker fields
Ratings and scores
File uploads and signatures (metadata only — the actual file content is not transferred)
Source, captcha, and boolean fields
How fields get mapped to your CRM contact properties:
The script tries to map fields in this priority order:
The form field's name attribute matches an Aesthetix CRM contact property or custom field key
The form field's <label> text matches an Aesthetix CRM display name
The form field's name matches the label text (case-insensitive)
If no match is found, the value is stored as unmapped_field so your team can identify and fix the mapping.
WordPress page builders are a major gotcha. Many popular WordPress page builders (Elementor, Divi, WPBakery, Beaver Builder, Bricks) and form widgets render form-like UIs using
<div>containers and JavaScript handlers — not real HTML<form>elements. The External Tracking Script cannot detect submissions from these. Page view tracking will still work, but form submissions will not sync to Aesthetix CRM.If you're on WordPress, use a plugin that outputs valid HTML forms — WPForms, Gravity Forms, or Contact Form 7 are the most reliable choices. To verify a form is compatible, right-click the form on your live site → Inspect → confirm there's a
<form>tag wrapping the inputs (not just a<div>).
Platform | Where to paste the script |
WordPress | Appearance → Theme Editor → Footer (or use the Insert Headers and Footers plugin). Paste before |
Squarespace | Settings → Advanced → Code Injection → paste in the Footer field |
Wix | Settings → Advanced → Custom Code → Add Custom Code → set to All Pages, Body (end) |
Shopify | Online Store → Themes → Edit Code → open |
Webflow | Project Settings → Custom Code → Footer Code → paste and publish |
Custom HTML | Paste directly before the closing |
Google Tag Manager | Custom HTML tag → trigger on All Pages → |
Single-page apps (SPAs): If your website is built as a React, Vue, or Next.js single-page app, page view tracking will only fire on the initial load by default. For attribution on subsequent in-app navigations, your developer needs to manually trigger a
page_viewevent on each route change. Reach out to our team if you need guidance on this.
Here's the scenario that breaks attribution for most practices:
A patient clicks a Google Ad → lands on your campaign landing page (with UTMs in the URL) → clicks "Schedule a Consult" in your menu → arrives on
/contact/→ submits the form there.
Without the Chat Widget or External Tracking Script on every page:
The form on /contact/ only sees /contact/ as the page it lives on
The original UTMs from the landing page URL are gone
The referrer at /contact/ is your own domain (your landing page), not Google
→ The conversion gets categorized as Direct Traffic or Referral, not Paid Search
With the Chat Widget or External Tracking Script on every page:
The original landing page URL (with UTMs) was captured anonymously when the visitor first arrived
That session data is preserved in the browser as the visitor moves around your site
When the form on /contact/ fires, the original session data is attached to the new contact
→ The conversion is correctly categorized as Paid Search
This is the single most common reason "my paid ad leads are showing up as Direct Traffic." If you're spending money on Google or Meta ads and your attribution looks broken, this is almost certainly why.
Your Setup | Recommended Pattern |
Website built entirely inside Aesthetix CRM | Pattern A — nothing to install, you're done |
External website + already using the Chat Widget | Pattern B — chat widget covers it |
External website + Chat Widget not desired | Pattern C — install the External Tracking Script |
External website + only single-page landing pages with forms on them | Pattern A behavior at conversion time, but you'll lose any cross-page nuance — Pattern C still recommended |
Mix of native landing pages + external main site | Use Pattern A on the native pages, Pattern B or C on the external site |
Inbound phone calls (additive to any of the above) | Pattern D — add Number Pools for call-channel attribution |
Patterns A, B, and C handle web-based conversions (forms, calendars, chat). But what about inbound phone calls? By default, calls show up with the source Others — useful to know they came in by phone, but not useful for understanding which marketing channel drove them.
Number Pools solve this. They're a dynamic-number-insertion system that swaps the phone number displayed on your website based on where each visitor came from. When that visitor later calls the number they saw, the system stitches the call back to the original web session — and the resulting contact gets the correct source attribution (Paid Search, Organic Search, etc.) instead of Others.
How it works in practice:
You purchase a small pool of phone numbers (typically 4–8) inside your account
You install the Number Pool tracking snippet in the footer of your website (this is a separate snippet from the Chat Widget and External Tracking Script — all three can run on the same site)
When a visitor lands on your site, the snippet detects their traffic source (paid search, organic, social, direct) and dynamically swaps the displayed phone number to a unique tracking number from your pool
Different visitors see different numbers — the visitor from Google Ads sees Number A, the visitor from organic search sees Number B, etc.
When a visitor calls the number shown on their page, the call is matched back to their session via cookie, attributed to the original source, and forwarded to your real business number
The call appears in your Call Reports tagged with the correct source — and if it generates a new contact, that contact's First Attribution will reflect the original web source instead of "Others"
To set up a Number Pool:
From the left navigation, go to Settings → Phone Numbers
Select Number Pools under Manage Numbers
Click Create Number Pool and select Visitors Activity as the tracking type
Choose which visitor sources you want to track (we recommend All Visitors for the most complete picture)
Add a Forwarding Number — this is your real business phone where the calls will route. Important: this cannot be another Aesthetix CRM number, or it will create a forwarding loop.
Choose your pool size (4 minimum). Larger pools are needed for higher-traffic sites — if too many concurrent visitors share the same number, attribution accuracy degrades.
Save the pool, then click Add/Edit Group ID to generate the Group Snippet. Copy this snippet and paste it in the footer of every page on your site (just like the External Tracking Script).
Verify it works by opening your site in an incognito window — you should see the displayed phone number swap based on how you arrived.
Pool sizing rough guide:
Monthly Site Visitors | Recommended Pool Size |
Under 5,000 | 4 numbers |
5,000 – 20,000 | 6 numbers |
20,000+ | 8 or more numbers |
Each number in the pool is billed at the standard phone number rate (same as any other phone number in your account).
Important limitations of Number Pools:
The visitor must visit your website first for the number swap to happen. Someone who sees a phone number directly in a Google Ad call extension or a print ad and dials it isn't going through the pool — that's just a regular inbound call.
For Meta (Facebook/Instagram) Ads, number pool attribution only works for click-to-call scenarios where the visitor clicks through to your website first. If the lead dials a pool number after seeing it on the site, attribution works. If they see your business number in a Meta ad and call directly, it doesn't.
Number pools require an active Group Snippet on your site to function. The snippet is separate from the Chat Widget and External Tracking Script — install all three if you need full attribution coverage across forms, chat, and calls.
Best for: Practices that invest meaningfully in paid ads or local SEO and want to know which channels drive their phone consultations. For most med spas, calls are still the dominant lead channel — so adding Number Pools to your attribution stack typically uncovers a significant amount of revenue that was previously categorized as "Others" with no source detail.
How to Setup Call Tracking With Number Pools
Learn how to setup attribution driven call tracking for Google Ads and Facebook Ads
Some setups will never produce useful attribution data, regardless of which tracking pattern is in place:
Setup | Why It Doesn’t Work | What Happens |
Iframe-based third-party forms (some Typeform embeds, JotForm popups, Calendly iframes) | The form lives in a separate browser context that the tracking script can't see into | No contact created via tracking |
Pure JavaScript widget forms (third-party plugins that don't render real HTML inputs in the page) | The External Tracking Script needs a real | No contact created via tracking |
Forms hosted on a different domain than where the tracking script is installed | Cross-domain session tracking is not supported in the standard configuration | Inconsistent / falls back to Direct Traffic |
Hidden or disabled form fields ( | Tracking script intentionally ignores hidden form elements as a privacy/security measure | No contact created via tracking |
Contacts created by Zapier or external API | Contact is created by an integration call, not from a tracked browser session | Categorized as Third-Party |
Contacts created manually by a team member | No browser session involved | Categorized as CRM UI |
Contacts created or modified by an internal workflow | No browser session involved — the contact was generated by automation | Categorized as CRM Workflows |
Inbound calls, SMS, email replies, WhatsApp messages, Messenger chats | These are non-web channels — there's no browser session to attribute | Categorized as Others (or inherits source from a Number Pool if used — see Pattern D) |
When a conversion event fires, the attribution engine looks at two things:
The full URL of the page the visitor was on when they converted (including all query parameters)
The referring domain — the website they were on right before they landed on your page (if available)
It then runs that data through a set of rules in priority order. The first rule that matches is the source that gets assigned. Once a match is found, the engine stops checking — so rule order matters.
Order | Rule | Assigned Source |
1 | The | Paid Search |
2 | A | Paid Search |
3 | A | Paid Search |
4 | The | Paid Social |
5 | The referring domain is a known social media site (Facebook, Instagram, LinkedIn, X, TikTok, etc.) | Social Media |
6 | The referring domain is a known search engine (Google, Bing, Yahoo, DuckDuckGo) | Organic Search |
7 | The referring domain is anything else (not social, not search) | Referrals |
8 | No referring domain and no tracking parameters present | Direct Traffic |
9 | The lead came in through a non-web channel (call, SMS, email, WhatsApp, Messenger) | Others |
10 | The lead was created manually by a team member inside the CRM | CRM UI |
11 | The lead was created or modified by an automated workflow inside the CRM | CRM Workflows |
12 | The lead was created by a third-party integration (Zapier, API, EMR sync) | Third-Party |
Notice that paid traffic rules run first. This is intentional. If a Google Ad lands a visitor on your page and they convert, the engine sees the gclid parameter (rule 2) and stops there — assigning Paid Search. It never bothers checking rules 5, 6, or 7.
This also means UTM parameters override referring domains in most cases. If you tag your Facebook ad URL with utm_source=fb_ad, the visitor will be categorized as Paid Social even if Meta strips the referrer header.
Pro tip: If you're seeing leads from your paid campaigns categorized as Direct Traffic, Organic Search, or Social Media instead of Paid Search/Paid Social, that's almost always a UTM parameter problem. See the Troubleshooting section.
Here's how attribution actually plays out across different visitor scenarios. Examples 1–3 all submit the same "Contact Us" form on the same contact page, but land in three different attribution buckets based on where they came from. Example 4 shows what attribution looks like when the contact never visits your website at all.
A prospective patient navigates directly to your website, browses a provider bio page, then submits the contact form.
Field | Captured Value |
Source | Direct Traffic |
Session URL |
|
Page URL |
|
Referrer | (empty) |
UTM Event Source |
|
Medium |
|
Form Name | Contact Us |
Device | iPhone (Safari, iOS 18) |
Why it landed in Direct Traffic: No referrer was captured, and no UTM parameters were present. Rules 1–7 didn't match, so the engine fell through to rule 8: no referring domain, no tracking URL → Direct Traffic.
What this tells you: This patient already knew about your practice — they typed your URL directly, used a bookmark, or clicked a link from somewhere that stripped the referrer (an iMessage, an in-app browser, a private browsing session, an email client). The Session URL is also revealing: they were specifically researching one of your providers, which is a strong consult-intent signal worth flagging for your front desk.
A prospective patient searches for a specific treatment on Bing, lands on your treatment page, navigates to the contact page, and submits the form.
Field | Captured Value |
Source | Organic Search |
Session URL |
|
Page URL |
|
Referrer |
|
UTM Event Source |
|
Medium |
|
Form Name | Contact Us |
Device | Windows desktop (Microsoft Edge) |
Why it landed in Organic Search: No paid UTMs, no Google or Microsoft click IDs. The referrer (bing.com) is a known search engine, so rule 6 matched → Organic Search.
What this tells you: This patient discovered your practice through SEO — and the Session URL reveals exactly which page ranked for their search ("Cosmelan MD depigmentation peel"). This is gold for your content strategy: it shows which procedure pages are doing the work of attracting cold demand. Note that Organic Search includes Bing, Yahoo, and DuckDuckGo, not just Google — don't underestimate the long tail of search engines, especially for desktop users.
A patient is browsing a partner website (a sister practice, a directory, or a press article), clicks through to your med spa, lands on the homepage, navigates to contact, and submits the form.
Field | Captured Value |
Source | Referral |
Session URL |
|
Page URL |
|
Referrer |
|
UTM Event Source |
|
Medium |
|
Form Name | Contact Us |
Device | iPhone (Safari, iOS 18) |
Why it landed in Referral: No paid UTMs, no Google click IDs, the referrer isn't a known social platform (rule 5 didn't match), and the referrer isn't a known search engine (rule 6 didn't match). Rule 7 matched: a referring domain that's neither social nor search → Referral.
What this tells you: This patient came from another website that links to yours. The Referrer field tells you exactly which one. For practices with sister sites (e.g., a plastic surgery practice that also operates a med spa), partner directories, RealSelf-style listings, or press mentions, monitoring the Referral source over time will show you which of those off-site assets are actually driving leads.
A potential patient sees one of your Instagram posts, sends a direct message asking about a treatment, and that conversation generates a contact in Aesthetix CRM via the Conversations integration.
Field | Captured Value |
Source | Social media |
Medium |
|
Medium ID |
|
Ig Sid |
|
Session URL | (empty) |
Page URL | (empty) |
Referrer | (empty) |
UTMs | (empty) |
Why the data is so sparse: This contact was never on your website. The conversion event happened entirely inside Instagram's DM interface. Aesthetix CRM only knows what Meta exposes through the messaging integration — which Instagram account received the message, and a session ID. There's no browser session to read URLs, referrers, or UTMs from.
What this tells you: This is the expected behavior for any DM-based channel (Instagram, Facebook Messenger, WhatsApp). You'll see the Source and Medium correctly identified, but you won't get the page-level or campaign-level attribution detail that web-based conversions produce. If you need to know which Instagram ad or post drove a particular DM, you'll need to cross-reference the timing and content with your Meta Ads Manager reports — Aesthetix CRM doesn't have visibility into that on its own.
The big takeaway: All three [main] of these submissions came through the same form on the same contact page. The conversion event itself is identical. But because attribution is based on the Session URL (entry point) and Referrer (where they came from) — not the Page URL where the form lives — three completely different sources were captured.
The Instagram DM example shows the other side of the coin: when there's no web session to attribute, the data captured is intentionally minimal. That's not a bug — it's a reflection of what the source channel actually exposes.
If you ever wonder "why did this contact get tagged as X?", look at the Session URL, Referrer, and Medium fields first, then walk those values through the rules table above. The answer will always be there.
To get your Google Ads traffic correctly categorized as Paid Search, you need to apply our Google Ads UTM template to your final URL. Aesthetix CRM uses these parameters to identify and group your campaigns inside the Ad Reporting dashboard.
This is case-sensitive. Copy and paste it exactly. Do not retype.
Name | Key | Value | Set By |
UTM Source |
|
| You (must be exactly |
UTM Medium |
|
| Google Ads (auto-populated) |
UTM Campaign |
|
| Google Ads (auto-populated) |
UTM Content |
|
| Google Ads (auto-populated) |
Match Type |
|
| Google Ads (auto-populated) |
Campaign ID |
|
| Google Ads (auto-populated) |
Ad Group ID |
|
| Google Ads (auto-populated) |
Ad ID |
|
| Google Ads (auto-populated) |
For full setup instructions including where to paste the template inside Google Ads, see the Google Ads Reporting Setup article.
Google Ads: All-In-One Guide
This comprehensive article combines multiple articles into one to help you get your Google ads properly setup and integrated with Aesthetix CRM.
To get your Meta Ads traffic correctly categorized as Paid Social, apply our Meta UTM template to your final URL.
{YourLandingPageUrl.com}?utm_source=fb_ad&utm_medium={{adset.name}}&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&campaign_id={{campaign.id}}
This is case-sensitive. Copy and paste it exactly. Note that Meta's dynamic placeholders use double curly braces
{{ }}— Google's use single{ }.
Name | Key | Value | Set By |
UTM Source |
|
| You (must be exactly |
UTM Medium |
|
| Meta Ads Manager (auto-populated) |
UTM Campaign |
|
| Meta Ads Manager (auto-populated) |
UTM Content |
|
| Meta Ads Manager (auto-populated) |
Campaign ID |
|
| Meta Ads Manager (auto-populated) |
The legacy value
utm_source=facebookhas been deprecated. Usefb_adgoing forward —
For full setup instructions including where to paste the template inside Meta Ads Manager, see the Meta Ads Reporting Setup article.
Facebook Ads: All-In-One Guide
Use this guide as your one stop to set up Facebook ads whether using lead forms or landing pages.
Understanding these limitations up front will save your team a lot of "why isn't this working?" troubleshooting later.
Attribution data is captured through one of two mechanisms:
A native Aesthetix CRM form, calendar, survey, chat widget, or order form — works on any site (native or external) where it's embedded
A standard HTML <form> element on a page where the External Tracking Script is installed — works for compatible third-party forms with real <form> tags
Forms that fall outside both — iframe-based embeds, popup-only forms, or JavaScript widget forms that don't render real HTML inputs (including most WordPress page builder form widgets) — cannot be tracked. Page views may still be recorded if the script is installed, but submissions won't sync.
Workaround: Either embed a native Aesthetix CRM form on your external website, OR replace your incompatible form with one of the recommended HTML form plugins (WPForms, Gravity Forms, Contact Form 7) and install the External Tracking Script.
If a visitor lands on Page A from a Google Ad and then navigates to Page B before submitting a form, the UTM parameters from Page A do not carry over on their own. By the time the conversion fires on Page B, the original ad click data has been lost.
Solution: Install one of the session-persistence layers covered above:
The Chat Widget on every page of your site, OR
The External Tracking Script on every page of your site
Either one will capture the original landing page data anonymously and attach it to the contact when they finally convert. See How attribution actually gets captured for detailed setup guidance.
For Organic Search attribution, you may see keywords listed as "Unknown (SSL)." This is because Google encrypts search queries — the search engine itself doesn't pass keyword data to your site. This is a limitation of the search engines, not Aesthetix CRM.
Certain apps (in particular, the iOS Facebook and Instagram apps when opening links in their in-app browsers) sometimes strip the referrer header. When this happens without UTM parameters, the lead can land in Direct Traffic even though they clearly came from social. This is why proper UTM tagging on paid campaigns is non-negotiable.
Adding extra parameters or modifying the template values can cause the rules engine to miss the match. Stick to the templates exactly as provided.
By default, calls into your business number are categorized as Others with no source detail — you know it came in by phone, but not which marketing channel drove it.
Solution: Set up Number Pools (Pattern D in How attribution actually gets captured). This dynamically swaps the phone number displayed on your website based on each visitor's traffic source, then attributes the resulting call back to that source. With Number Pools in place, calls inherit the same source classification as web conversions (Paid Search, Organic Search, etc.) instead of falling into Others.
For inbound SMS, email replies, and other text-based channels, there's no equivalent solution today — these will continue to be categorized as Others regardless of your tracking setup.
Modern browsers — particularly Safari on iOS and macOS — have aggressive privacy features (Intelligent Tracking Prevention, content blockers, private browsing modes) that can clear the browser storage used by the Chat Widget and External Tracking Script. When this happens:
Anonymous session data captured on Page A may be cleared before the visitor reaches Page B
The conversion will fall back to Direct Traffic or Referral
This is more of an issue for visitors who:
Use Safari Private Browsing
Have third-party cookie blocking enabled aggressively
Wait more than 7 days between landing on the site and converting (iOS ITP clears tracking data after 7 days)
Workaround: This is a browser-level limitation, not something Aesthetix CRM can override. The best mitigation is to make your conversion path short — keep the form on or near the landing page so the conversion happens in the same session.
When a contact is created from a Facebook Messenger or Instagram Direct Message conversation (via the Conversations integration), the attribution captured is intentionally minimal because there's no browser session to attribute. You'll typically only see:
Field | Captured Value |
Source | Social media |
Medium |
|
Medium ID | The unique ID of the connected Page or Instagram account |
Ig Sid (Instagram only) | The Instagram session ID for the message thread |
You will not get session URLs, referrers, UTMs, click IDs, or device data — because the contact never visited your website during the conversion event. The system only knows which channel they came from and which connected account received the message.
This is a fundamental limitation of message-based channels, not a configuration issue. The same applies (with even less detail) to WhatsApp messages and other DM-based integrations.
What this means for your reporting: Don't expect to see Meta Ad campaign-level attribution on Messenger/DM leads, even if those leads originated from a click-to-message ad. If campaign-level attribution on Messenger/DM leads is critical for your practice, you'll need to combine the Aesthetix CRM data with reporting from Meta Ads Manager directly.
This is by far the most common attribution problem. There are two possible root causes — work through them in order.
Root cause #1: Missing session-tracking layer on a multi-page journey
If your landing page and your conversion page are different pages, you need either the Chat Widget or the External Tracking Script installed on every page. Without that, the original UTMs from the ad-clicked landing page are lost the moment the visitor navigates to a different page.
To diagnose:
Open your landing page in an incognito browser
Append a test UTM string: ?utm_source=adwords&utm_medium=test&utm_campaign=diagnostic
Click an internal link on the landing page (e.g., "Contact" in the menu) to navigate to your conversion page
Submit the form on the conversion page
Check the new contact's attribution panel. If the source shows Direct Traffic or Referral instead of Paid Search, your session-tracking layer is missing or not firing on every page
Root cause #2: UTM parameter problems on the ad itself
If your visitors land on the conversion page directly from the ad (no navigation in between) but attribution still shows wrong, the issue is in your ad's URL configuration:
Verify case sensitivity. utm_source=AdWords is not the same as utm_source=adwords. Lowercase only, exactly as provided in the template.
Verify spelling. A typo like utm_souce (missing the r) will silently fail. The engine looks for the exact key.
Test the URL manually. Copy the final URL from a live ad preview, paste it into a fresh incognito browser, submit the form yourself, and check the contact's attribution data.
Check that you used the correct template. Google Ads uses utm_source=adwords. Meta uses utm_source=fb_ad. Mixing them up will land in the wrong category.
Check the Session URL field on the attribution record (not the Page URL — those are different). The Session URL shows the exact URL the visitor was on when they first entered the session, including all parameters and the referrer at that moment. Run that URL and referrer through the rules table above — the first rule that matches will tell you exactly why it was categorized that way.
If the Session URL doesn't include the UTM parameters you expected, your ad isn't tagging the landing URL correctly — see the steps above.
If a contact has no attribution data at all, one of the following is true:
The contact was created manually (CRM UI) or via integration (Third-Party) and never had a tracked conversion event
The conversion event happened on a third-party form, not a native Aesthetix CRM asset
The contact was created before attribution tracking was active on the form/calendar/widget they used
A few things to check, in order:
Verify the script is actually on the page. Right-click the page → View Source → search for external-tracking.js. If it's not there, the script wasn't added or your CMS didn't save it.
Verify the data-tracking-id attribute is intact. Some Google Tag Manager configurations strip attributes when wrapping scripts. If your console shows Tracking: Missing data-tracking-id attribute, GTM is the culprit. Either fix the GTM tag to preserve attributes, or install the script directly in your site footer.
Enable debug mode. Add data-debug="true" to the script tag and reload the page with browser DevTools open. You should see tracking logs in the Console.
Check for cookie blocking. Browser privacy extensions (uBlock Origin, Privacy Badger), enterprise content blockers, or Brave's built-in shield can block the tracking script entirely. Test in a different browser without extensions.
Check for CORS errors. In DevTools → Network tab, filter by the tracking request. If you see CORS errors, the domain may not be properly connected to your account — reach out to support.
Single-page apps don't trigger a fresh page load when the user navigates between routes — the URL changes but the script doesn't fire again. As a result, only the initial page load is tracked.
To fix this, your developer needs to manually trigger a page_view event after each route change. This is a common pattern for SPAs and is a one-time setup. Reach out to our team for the specific implementation guidance.
If your team is building dashboards, custom integrations, or pulling attribution data into a data warehouse, the same attribution data shown in the UI is exposed through the Aesthetix CRM API. When you call the Get Contact endpoint, the response includes two attribution objects:
attributionSource → corresponds to First Attribution in the UI
lastAttributionSource → corresponds to Latest Attribution in the UI
Both objects have the same field structure. Here's the full schema:
API Field | Type | Description |
| string (required) | The URL where the conversion event fired |
| string | Campaign name (from |
| string | Platform-assigned campaign ID |
| string |
|
| string |
|
| string |
|
| string | Referring URL |
| string | Google Ads click ID |
| string | Meta (Facebook/Instagram) click ID |
| string | Microsoft / Bing Ads click ID |
| string | Display & Video 360 / Google Display click ID |
| string | Meta click cookie value |
| string | Meta Pixel browser cookie value |
| string | Meta CAPI event deduplication ID |
| string | Visitor's browser user agent string |
| string | Visitor's IP address |
| string | Conversion event type ( |
| string | Unique ID of the specific form, calendar, or widget that fired the event |
The contact response also includes a top-level visitorId field — a unique identifier assigned to each chat widget visitor, useful for stitching pre-conversion chat sessions to the resulting contact.
Common use cases:
Pulling attribution data into a BI tool (Looker, Tableau, Power BI) for cross-channel ROI analysis
Building a custom dashboard for multi-location practices that need consolidated reporting
Sending conversion events back to ad platforms via custom server-side integrations
Deduplicating leads across the CRM and an EMR or other downstream system
Aesthetix CRM API documentation, authentication, and full endpoint reference is available through your account team. API access requires an active OAuth integration or private integration token; reach out for setup details.
For agencies: If you manage multiple Aesthetix CRM accounts and want a single attribution dashboard across all of them, the Get Contact endpoint combined with the Workflows API and Reporting API gives you everything you need to build a custom multi-account reporting layer.
Q: Will attribution work if I embed an Aesthetix CRM form on my WordPress / Squarespace / Shopify site?
Yes — the embedded form itself will capture attribution at the moment of submission. But for cross-page browsing journeys (visitor lands on Page A from an ad, then navigates to Page B and submits), you'll also need either the Chat Widget or the External Tracking Script installed on every page. Otherwise the original ad data from Page A will be lost by the time they reach Page B.
Q: Should I use the Chat Widget or the External Tracking Script for attribution?
If you already use (or want to use) the Chat Widget on your site, it handles attribution tracking automatically — no separate script needed. If you don't want a chat interface on your website, install the External Tracking Script instead. They both serve the same attribution purpose; the Chat Widget just adds the chat functionality on top. There's no benefit to installing both — pick one.
Q: Does the External Tracking Script work with iframe-based forms?
No. The script needs to see a real <form> element in the page DOM to detect submissions. Iframe-based forms (and many third-party form widgets) live in a separate browser context that the script can't access. If you need attribution on a third-party form, replace it with an embedded Aesthetix CRM form.
Q: I have the External Tracking Script installed on my WordPress site but form submissions aren't syncing. Why?
This is almost always because the form on your site is built with a page builder (Elementor, Divi, WPBakery, Beaver Builder, Bricks) or a JavaScript widget that renders form-like UI using <div> elements instead of a real HTML <form> tag. The script can't detect those submissions. Either rebuild the form using WPForms, Gravity Forms, or Contact Form 7, or replace it with an embedded Aesthetix CRM form. To verify: right-click your form → Inspect → look for <form> wrapping the inputs. If you see only <div> elements, that's the issue.
Q: Can I track page views without form submissions?
Yes — once the External Tracking Script is installed, page views are tracked anonymously and stored in the visitor's browser. You can use the Page View workflow trigger to fire automations based on which pages a visitor has viewed, even before they convert. Note that no contact record is created until a form submission ties the anonymous activity to a real person.
Q: How do I track which marketing channel drove an inbound phone call?
Use Number Pools (Pattern D in How attribution actually gets captured). Without a number pool, calls are categorized as Others with no source detail. With a number pool, the phone number displayed on your website dynamically swaps based on where each visitor came from, and calls to those tracked numbers are attributed back to the original source.
Q: Why don't my Instagram DM leads have any URL or campaign data?
Because the conversion happened entirely inside Instagram — the lead never visited your website. The system can only capture what Meta exposes through the messaging integration: the source channel (Social media), the medium (instagram), and your connected account ID. Session URLs, referrers, and UTMs require a browser session, which DM-based conversions don't have. This is the expected behavior for any DM, Messenger, or WhatsApp lead. See Limitation #8 for more detail.
Q: Can I run the Chat Widget, External Tracking Script, AND Number Pool snippet on the same site?
Yes — all three can coexist on the same site and they don't conflict. They handle different attribution capture jobs: the Chat Widget covers chat conversions and acts as a session tracker, the External Tracking Script covers form submissions and page-view-triggered workflows, and the Number Pool snippet handles inbound call attribution via dynamic number insertion. For a complete attribution picture across forms, chat, and calls, you'd typically run two of the three: (Chat Widget OR External Tracking Script) plus the Number Pool snippet.
Q: How do I export attribution data into a spreadsheet?
Use the custom contact fields that Aesthetix CRM auto-populates with attribution data — these are included in standard CSV exports from the Contacts tab. The native attribution data on the Activity tab is not included in CSV exports, but the custom fields (First Attribution Session Source, Last Attribution Session Source, UTM Source, UTM Campaign, UTM Content, Attribution - Source URL, Attribution - GCLID, Attribution - FBCLID) cover the most-used values. See Attribution data in custom contact fields for the full list.
Q: Can I use attribution data as merge fields in emails or SMS?
Yes — through the custom contact fields. You can reference any of the mapped attribution custom fields the same way you'd reference any other contact field (e.g., {{contact.last_attribution_session_source}} in a template). The native attribution panel data is not directly available as merge fields, which is why we set up the custom field workflow in the first place.
Q: Why are the UTM Source / UTM Campaign / GCLID / FBCLID fields empty on so many of my contacts?
Because UTM parameters and click IDs only exist on URLs that were explicitly tagged with them — typically by paid ad campaigns. Contacts who arrived via organic search, direct traffic, organic social media, referrals, inbound calls, or DM channels don't have UTMs because no one tagged the URL they arrived through. This is expected and normal. If you want UTMs on your organic content (Instagram bio link, email newsletter links, partner referrals), you'll need to manually add UTM parameters to those URLs yourself. See the table in Why some custom fields will be empty for many contacts.
Q: What is the "CRM Workflows" attribution source?
"CRM Workflows" appears on contacts that were created or substantially modified by an automated workflow inside Aesthetix CRM (as opposed to manual entry, which produces "CRM UI"). For example, if you have a workflow that auto-creates a contact from a webhook trigger, that contact's source will be CRM Workflows. This is a relatively new source type and may not appear in older help materials. It's a normal source — not an error.
Q: Why does my contact show one source at the top of their record and a different source on the attribution panel?
Because those are two different fields. The single "Source" field at the top of the contact record is the Contact Source — a free-text label set by the form, URL parameter, or system default. The source shown on the Activity tab attribution panel is the Attribution Source — the standardized marketing channel categorization (Paid Search, Organic Search, etc.) assigned by the rules engine. Both are correct; they answer different questions. See Contact Source vs. Attribution Source for the full explanation.
Q: I want all leads from a specific landing page to be tagged with a custom source label — how?
Use the ?source= URL parameter. Append it to your landing page URL (e.g., https://yoursite.com/landing?source=summer_promo_2026) and any form submitted from that page will be tagged with that custom Contact Source label. This overrides the form's built-in source value. Note: this only affects the Contact Source field, not the Attribution Source — the Attribution Source is still determined by UTMs and referrer.
Q: If a returning lead submits another form, does their Contact Source get overwritten?
No. Aesthetix CRM workflows that update Contact Source always check whether the field already has a value — if it does, the workflow leaves it alone. This means the Contact Source you see on a returning lead is the original source from when they first entered your system, not the most recent form they happened to submit. (If you want to track the most recent interaction channel, use the Last Attribution Session Source custom field instead — that one updates on every new conversion.)
Q: Do Trigger Link clicks update attribution?
Yes. When a contact clicks a Trigger Link in an email, SMS, WhatsApp, GMB, or Messenger/DM, the click is recorded as a tracked event on their activity timeline and their Latest Attribution is updated to reflect that the most recent interaction was a Trigger Link click. The First Attribution remains locked to whatever was originally captured.
Q: How long is anonymous session data stored before a contact submits a form?
Session data is stored in browser storage and persists across navigation within the same browsing session. It can persist across multiple sessions for some time, but iOS Safari's Intelligent Tracking Prevention will typically clear it after 7 days of inactivity. For best results, design your conversion path so visitors convert in the same session they arrive in.
Q: What happens to attribution if a contact converts twice in the same session?
Latest Attribution will update to reflect the most recent conversion event. If both conversions happen on the same visit (same UTMs, same referrer), the data will look identical — but the timestamp will update.
Q: Can I see attribution data in the Reporting dashboard, not just on individual contacts?
Yes. The Ad Reporting dashboards roll up attribution data across all your contacts and let you filter by source, campaign, ad group, and more. See the Ad Reporting articles for details.
Q: How does attribution interact with the Facebook/Meta Conversions API (CAPI)?
They serve different purposes. Native attribution categorizes contacts inside Aesthetix CRM for your own reporting. CAPI sends conversion events back to Meta so Meta can optimize ad delivery. You should set up both — they don't conflict.
Q: Does Aesthetix CRM support TikTok Ads attribution?
Currently, the rules engine recognizes fb_ad, linkedin_ad, twitter_ad, and reddit_ad as Paid Social signals. TikTok-tagged URLs (e.g., utm_source=tiktok_ad) will currently fall into Social Media or Referrals depending on the referrer. If TikTok is a major channel for your practice, contact our team — we can help you tag URLs to land in a meaningful category.
Q: Will attribution capture if a patient clicks an SMS link and submits a form?
Yes — but the source assigned will be based on the URL parameters in the SMS link. If you don't add UTM parameters to your SMS links, the conversion will likely be categorized as Direct Traffic. We recommend tagging SMS campaign links with utm_source=sms&utm_campaign={campaign_name} to track their performance.
Q: Can I edit attribution data after it's been captured?
First Attribution is locked once captured and cannot be edited. Latest Attribution updates automatically on every new conversion event. Neither can be edited manually through the UI.
Q: Does attribution work on my mobile-optimized landing page?
Yes. The attribution engine doesn't care about device type — it reads the URL and referrer, both of which are present on mobile and desktop equally.
Q: What are the Fbp, GA Client ID, and FB Event ID fields on the attribution panel?
Those are tracking identifiers, not attribution sources. They're captured automatically alongside attribution data so they can be used downstream:
Fbp is the Meta Pixel browser cookie. It's needed to send conversion events back to Meta via the Conversions API (CAPI), which lets Meta optimize ad delivery against your actual closed leads.
GA Client ID is the Google Analytics client cookie. It's used to stitch together user activity between your website's GA4 tracking and conversion events fired in Aesthetix CRM.
FB Event ID is a unique ID generated for each conversion event so that browser-side Pixel events and server-side CAPI events can be deduplicated by Meta.
You don't need to do anything with these fields directly. They're stored so the system can use them when sending data to Meta and Google for ad optimization.
Need help setting up attribution tracking for your campaigns? Setup of paid ad attribution tracking falls outside the standard support scope. If you'd like our team to configure your Google Ads or Meta Ads UTM templates, submit a Custom Build Request and we'll get you a quote.