Your CRM reports fewer paid leads than Google or Meta because it infers each lead's source instead of reading the UTM, so a lead whose account is created inside the product is filed as offline, organic or direct even when it came from a paid click. The fix is to make the UTM the source of truth, join the ad platforms and the CRM in one governed layer, and send conversions back, so the same layer that measures attribution can also act on it.
Because the CRM guesses where each lead came from, and the guess hides paid. In one real analysis, a Google channel showed 4 leads at $908 per lead in the CRM, while the true figure was 46 leads at $79 per lead, one of the cheapest channels in the account. 42 paid leads were hidden, in a single month, a single channel, a single report. The ad platform was never the problem. The default way of measuring hides paid from everyone.
One clause changed the picture: a channel went from 4 reported leads to 46, and from $908 to $79 per lead. Same spend, same campaign, different number underneath.
Paid media lives across at least five systems, Google, Meta, LinkedIn, TikTok and the CRM, and stitching them together is roughly a dozen manual integration problems: getting the lead into the CRM, keeping the origin through the journey, normalizing columns and currencies, reconciling totals, tying spend to revenue. The result is that the number a CEO opens in the CRM is not the number the campaigns actually produced, and someone spends the week explaining the gap.
Because it stamps a source it infers, not the one the click carried. A field like hs_analytics_source is the platform's automatic guess at where a contact came from, not the UTM. When an account is created inside the product without passing through a tracked page, the CRM often labels it offline, even if the person clicked a paid ad with a UTM thirty seconds earlier. So a lead from paid search is recorded as offline, organic, or direct, and when you filter the CRM for paid, it returns almost nothing, because the best leads, the ones that became accounts, were filed elsewhere. You are not measuring your ads. You are measuring the CRM's guess about your ads.
Because each platform is a walled garden that only counts what happened inside it. One dashboard shows the conversions that platform claims, and the next does the same. None of them knows the person saw a social ad, downloaded an ebook, then ran a branded search three days later. Add the dashboards together and you double-count conversions that still do not match real sales. Three sources of truth is zero sources of truth. It is the same failure described in why AI agents give different answers on the same data: without one governed definition, every tool reports its own number.
Make the UTM the source of truth and read it instead of the CRM's inferred field. The UTM is what the team stamped when the campaign went live, not an algorithm's inference. In a governed layer where the data is yours to query, the correction is a single clause.
| The query | What it keys on | What happens to a paid lead |
|---|---|---|
| hs_analytics_source IN ('PAID_SEARCH', 'PAID_SOCIAL') | the CRM's inferred source | a product-created account lands as offline, organic or direct, so paid is undercounted |
| utm_medium IN ('paid', 'paid_social', 'cpc') | the UTM captured at the click | the lead keeps the channel it actually came from, and the hidden paid leads reappear |
Swapping the first clause for the second is the whole fix, and the Google channel goes from 4 leads to 46. It only works because a layer underneath has already joined contacts, clicks and leads and exposed a clean utm_medium field. In raw form that UTM is buried across dozens of tables with mismatched column names, time zones and currencies, which is why nobody does the join by hand on a Friday afternoon. Standardizing messy UTMs (cpc, ppc and paid for the same thing) once, in the layer, and writing the clean value back to the CRM beats a brittle CRM workflow that breaks on the first exception.
You see the full funnel, from spend to closed sale, plus three cuts no single dashboard can give you. With every channel attributed the same way, a platform that shows beautiful engagement in its own panel can turn out to have produced no sales in the month, which only becomes visible when the channels sit side by side and the conversion that counts is a meeting or a sale, not a click. Three cuts separate guessing from deciding.
| Cut | What the combined layer reveals |
|---|---|
| Lead quality, not volume | Two campaigns with near-identical lead volume looked tied on the dashboards. Crossed with the CRM, one brought 11% corporate email and zero sales; the other over 50% B2B, and closed. Same volume, opposite quality. |
| Speed by channel | Meta closes fast, around 10 days from lead to sale; Google takes closer to 40 days. Judge both in the same short window and you pause Google for not converting, when its sale has simply not matured. |
| Dayparting, by real conversion time | Broken out by the hour the person actually converted, not the hour the lead reached the CRM, the evening 18:00 to 23:00 brought more leads and cheaper ones, peaking around 22:00. |
Corporate versus personal email is a textbook example of context that has to live next to the data, so an agent reads the rule instead of guessing it, covered in context engineering for AI agents.
Attribution is step one; the value is the loop. Once the layer measures correctly, it can act, and it writes as well as reads.
That write-back is what turns a reporting layer into an operating one, and it is the natural next step toward running ads with an agent rather than only reporting on them. Reaching the data over a standard protocol is covered in what an MCP server for data is, and when you need one.
Nekt is a data platform that gives AI agents governed context, and attribution is a clean example of the three parts it covers.
The payoff is accuracy and reach at once: one source of truth instead of a secret spreadsheet tab, and a single query that crosses every channel instead of a manual join across exports.
Because the CRM infers a source instead of reading the UTM. When a contact is created without passing through a tracked page, for example an account created inside the product, the CRM stamps it offline, organic or direct, even if the click that led there was paid. The paid origin sits in the UTM, not in the CRM's inferred field.
The UTM, for paid attribution. It is the value the team stamped on the campaign, not an algorithm's guess. The CRM's inferred field is convenient but it undercounts paid, because it reassigns product-created and untracked contacts away from the channel that actually drove them.
Yes, once the sources live in one governed layer with UTMs standardized, because the query becomes a single filter rather than a manual join across exports. The modeling is the real work; after that, the question is asked in plain language or one line of SQL, and anyone comfortable with spreadsheet lookups can read what is happening.