Skip to main content
Terminus
Contents
The Letter's JourneyChapter 7 · ~10 min read

The CRM and the Warehouse

Analytics stops at the visit. How your values reach the lead, the deal and the revenue: hidden form fields, first, last or every touch, and the join that puts spend and revenue on one row.

On this page
The chapter in 5 min, as a video.Next video: Chapter 8 · Mistakes and Audits →

Here is a lead record from Stride’s CRM, as it would have arrived had the sign-up form stayed as it was:

FieldValue
First nameMaya
Emailmaya@example.com
Form10% off your first order
Signed upthe sale’s second week
Sourceempty
Mediumempty
Campaignempty

Where did Maya come from?

You can’t say. Neither can anyone at Stride who opens this record, today or in a year.

Chapter 6 left the spring sale in good shape, and ended on a question. The names match the links. What happens when a visitor becomes a lead?

This record is what happens, unless something is built to stop it.

It’s easy to treat the campaign report in analytics as the whole answer. It shows which campaigns brought visits and conversions, so the job ends when the link is tagged.

But the lead, the deal and the revenue are recorded in other systems, and those systems see only what reaches them. So the bill arrives in three places:

  • A perfectly tagged visit turns into a lead with no source.
  • Sales can’t tell where anyone came from.
  • Chapter 6’s join, spend against the revenue analytics saw, stops at analytics. The leads, and any revenue recorded beside them, have nothing to join on.

Analytics stops at the visit

Here’s what analytics recorded for Maya over the same two weeks:

VisitSourceMedium
Facebook ad, launch weekfacebookpaid_social
Instagram ad, a week laterinstagrampaid_social

Both carry the campaign spring_sale-runners-2025_03. Both rows are perfect. The record above is blank. They describe the same person in the same fortnight.

Analytics did its job. Its job ends at the visit.

The lead, and later the deal and the revenue, are written somewhere else. A CRM (customer relationship management system) keeps one record per person and per deal: who they are, what they bought or might buy, and where they came from, if anyone told it. Marketing automation is the system beside it that runs the forms and the emails: a sign-up form like Stride’s, and the emails that follow it. On the tool map, forms, CRMs and marketing automation sit together at stage 4.

The lead record is the fourth envelope from the introduction, the one sales opens. Like every envelope, it carries only what was written into it. Nobody wrote anything into Maya’s.

The CRM won’t complain. An empty field is a perfectly valid field.

A form sends only its own fields

So where did Maya’s values go? Follow her first visit:

  1. She taps the Facebook ad and lands on stride.com/spring-sale?utm_source=facebook&utm_medium=paid_social&utm_campaign=spring_sale-runners-2025_03. The values are in the address, and analytics reads them from there.
  2. She clicks through to a product page. Its address carries none of the values.
  3. She leaves.
  4. A week later the Instagram ad brings her back, and she signs up for 10% off her first order.

The form sends what she typed into it: her first name, her email.

A form sends its own fields and nothing else. The address she landed on a week earlier isn’t one of them, and by the time anyone fills in a form they’ve usually moved to another page, or left and come back days later.

Analytics never had this problem: it read the values from the address the moment she landed.

The form reads nothing but itself. Nothing carries the values across that gap unless the site does two things:

  1. Keep them in the browser. On landing, a small script reads the values from the address and saves them, in a cookie or in browser storage. Either one belongs to one browser on one device, and either can be cleared.
  2. Copy them into hidden fields. A hidden field is a form field the visitor never sees. It’s sent with the form like any other field. The script fills it from what it saved, before the form goes:
<input type="hidden" name="first_touch_utm_campaign">
<input type="hidden" name="last_touch_utm_campaign">

The full recipe, including how long to keep the values, is in the Cheat Sheet.

There’s a second way across, with different rules. A CRM can bring its own tracking script for your site, which records each visit and fills a source on the lead by itself:

Hidden fields you add

Your exact values, in fields you named. You build it: the script, the fields, and a home for each value in the CRM.

Lean this way when the record has to carry your letter as written: the campaign value a join will need, the values your reports group by.

The CRM’s own tracking

Its script records the visit by its own rules, into its own categories. No setup, and no say in what it keeps.

Lean this way when its categories answer your questions, and nothing downstream needs your exact values.

The second is Chapter 2’s lesson again, one stage later: the tool picks the category. You get someone else’s grouping of your values, not your letter. Which CRMs do this, and what their categories hold, is in The Tool Landscape, with a checked date.

The same lead, with hidden fields

Now put the hidden fields on Stride’s form, two sets of them, and run Maya’s two visits again:

On the leadSourceMedium
Beforeemptyempty
First touchfacebookpaid_social
Last touchinstagrampaid_social

The campaign fields, empty before, now read spring_sale-runners-2025_03 for both touches.

  1. First touch

    Launch week

    Facebook ad

    facebook / paid_social

  2. Last touch

    A week later

    Instagram retargeting ad

    instagram / paid_social

  3. Outcome

    Signs up for 10% off her first order

Maya's two visits, both in spring_sale-runners-2025_03. The first touch is what brought her in; the last is what brought her back the time she signed up.

Facebook found her. Instagram brought her back. The campaign value is the same on both, so both touches belong to the spring sale.

One aside for the expert: retargeting is the audience, not the medium. The Instagram ad is still paid_social.

Now take the hidden fields away again and look at what changes. Analytics still has both visits, every value intact.

The visit didn’t change. Only the lead lost its letter.

Decide what each record keeps

Why two sets of fields? Because a field keeps a value in one of two ways:

  • First-touch fields are written once and never overwritten. They answer: what brought this person in?
  • Last-touch fields are rewritten on every tagged visit. They answer: what brought them back the time they converted?

Whatever a record doesn’t keep can’t be added later.

It’s Chapter 1’s rule (you can remap what was recorded, never record what wasn’t), now applied to the lead. A CRM that keeps only last touch has overwritten every first visit as it went, and no report can bring one back.

There’s a third option, for the middle of the journey. A touch history keeps one row per tagged visit, either in the browser or sent to the warehouse as events (a row per visit, as it happens), and ties the rows to the lead when the form is sent. It’s the only way the middle survives.

FirstLastEvery
Keepsthe first tagged visit, oncethe latest tagged visitevery tagged visit
Answerswhat brought them in?what brought them back?what happened between?
Costshidden fields; CRM fields written oncehidden fields, refilledengineering and storage
Losesother devices; visits before storage was clearedevery earlier visitwhat the browser never saw

First, last or every touch is a choice of what each record keeps and what each costs to build. The first two take a few hidden fields.

The third is a project.

Which touch gets the credit for a sale is a different question, answered by an attribution model, and that’s Chapter 11’s. Here the question is only which values the record keeps.

The deal and the revenue need the values too

A lead isn’t the end of the trail. If your CRM keeps the deal as a separate record from the lead, the deal carries the lead’s values only if they’re copied onto it, or if it stays linked to the lead. Otherwise the deal starts blank, and the trail ends one step later than before. Stride sells through checkout, so picture Maya’s values in a business that sells through deals, with a CRM that keeps the deal apart from the lead:

On the dealCopiedNot copied
Amountrecordedrecorded
Source, firstfacebookempty
Source, lastinstagramempty
Mediumpaid_socialempty

One person, one lead, the values sitting in the CRM. The deal in the Not copied column never got them, and the deal is where the money gets recorded.

Revenue is recorded wherever the sale happens: a deal marked won in the CRM, or an online order. Wherever that is, it needs the values too.

With the values on every record, Chapter 6’s join reaches the CRM. It matches two things:

  • The campaign: Meta’s campaign_name against the lead’s campaign, the same exact string.
  • The platform: Meta’s rows (the platform is added as a column when the export loads) against leads whose source is one of Meta’s, facebook or instagram, both paid_social.

The campaign alone isn’t enough. The newsletter and the QR code carry spring_sale-runners-2025_03 too, and their leads didn’t come from Meta’s money.

Meta's spend export

Meta Ads, one row per campaign per day

  • date
  • platform
  • campaign_name (join key)
  • spend
  • clicks

campaign_name and first_touch_campaign both hold

spring_sale-runners-2025_03

Stride's leads

the CRM, one row per lead

  • first_name
  • signed_up
  • first_touch_source
  • first_touch_campaign (join key)
  • last_touch_campaign
Joined here on the first-touch campaign, character for character, and on the platform: Meta's rows meet only leads whose first-touch source is facebook or instagram. A lead whose campaign is spelled differently doesn't join.

Add analytics, which has the visits by utm_campaign, and three systems meet on the same campaign value: the money that went out, the visits it bought, and the leads that came back, with every deal and order that carries their values. Experts call this closed-loop reporting, and it’s the term to search for when you want to see how others build it.

The join itself can run in three places. Each costs more to set up and less to repeat:

Where it runsSetupEach repeat
A sheet of two exportsnoneall of it, by hand
A BI tool (stage 6 dashboards, such as Looker)a connection per sourcea refresh
A warehouse that pipelines fill daily (stage 5)a pipeline per system, and upkeepnone: it’s there each morning

If the question comes once a quarter, the sheet is fine. If it comes every Monday, the sheet is a part-time job.

Your situation

Four things decide what your version of this looks like:

  • If you sell through leads (a form, then a conversation or a deal), the lead is where the values land first, and the deal has to inherit them. If you sell straight to checkout, the order is the record, and it needs the values the way a lead would.
  • If revenue is recorded in the CRM, in your store, or in both, every place that records a sale needs the values, or a link back to a record that has them.
  • If first visit and sign-up are weeks apart, first touch matters more, and the browser storage is likelier to be cleared or left behind on another device. If people sign up on their first visit, first and last touch are the same visit.
  • If nothing joins your systems yet, the join starts in a sheet. If a BI tool or a warehouse already holds spend and visits, the CRM is one more source on the same key.

What changes

DecisionBeforeAfter
Where the job endsthe analytics reportthe trail ends at the visit; the lead, deal and revenue need the values after it
Lead formstyped fields onlyyour values in hidden fields, or the CRM’s tracking and its categories, knowing what each keeps
Source on a leadwhatever the tool storedfirst, last or every touch, by the question and the cost
Spend vs revenueby hand, when askedspend, leads and revenue joined in one place on the same campaign value, where it fits how often it’s asked

Where the rule lives

Every system after the link keeps whatever it’s given. The hidden fields copy the link’s values unchanged, the CRM stores them, and the warehouse joins on them, typo and all; none of them knows that a stray Spring_Sale was a mistake. So the one place to get a value right is where the link is made. Cleaning it in the CRM later is a rule beside the path: someone has to remember it, every time, in every system the value reached.

Check yourself

Your CRM keeps only last-touch values. The CEO asks which campaigns find new customers. Can you answer for the leads you already have?

Show answer

No. Last touch is rewritten on every tagged visit, so what first brought each lead in is gone, and it can’t be added back. First-touch fields, written once, answer it from now on.

Your analytics report shows the spring sale's visits with every value, and the CRM shows its new leads with empty source fields. Where did the values stop, and what carries them across?

Show answer

At the visit: the form sent only the fields people typed. Keep the values in the browser when someone lands and copy them into hidden fields when the form is sent, or rely on the CRM’s own tracking and its categories.

Meta's export lists spend under spring_sale-runners-2025_03; some leads' first-touch campaign reads Spring_Sale-runners-2025_03. What happens to the join, and where is the fix that stops it coming back?

Show answer

Those leads don’t join: the join key matches exact strings. Remap the history once. The lasting fix is where the link was made, because the hidden fields copied it faithfully.

In one line

Analytics stops at the visit. The values reach the lead, the deal and the revenue only if a form carries them there, so decide which touches each record keeps, and join it all on the same campaign value.

Before the next chapter

Open one of your lead forms from a tagged link, fill it in, and open the record it creates. If the source fields are empty, that's where your trail ends.

Next · Chapter 8 · Mistakes and AuditsEvery envelope carries the same letter. What happens when someone types it wrong?