> ## Content Index
> Fetch the complete content index at: https://www.livain.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Attribution only gets real when it joins the order book: matching four months of web enquiries to the ERP
- URL: https://www.livain.com/blog/attribution-join-order-book-erp-web-enquiries/
- Published: 2026-10-06T07:00:00.000Z
- Updated: 2026-10-06T06:59:59.000Z
- Description: Joining website enquiries to an ERP's quotations and confirmed orders is an entity-resolution problem, not a VLOOKUP. What the match ladder, the company-level unit of attribution and an eighty-day lag tail do to your read on lead quality.
- Author: Remco Livain
- Tags: Attribution, Marketing Analytics, Google Ads, Lead Generation, Marketing Ops

In the ERP of the natural-stone supplier I look after, a private buyer does not have an email address. They are booked as a cash sale. Their name exists in exactly one place: inside a free-text reference field, next to a street and a postcode, because that field is really for naming the building site.

That single detail is why connecting website enquiries to actual orders took a day of work rather than a VLOOKUP. It is also why most companies never do it, and keep scoring lead quality in the ad platform instead.

### The ad platform can only tell you what happened on your website

Two weeks ago I wrote that [a price-list download is not a lead](https://www.livain.com/blog/price-list-download-is-not-a-lead-long-lead-time-attribution/). That was an argument from the shape of the funnel. Now there is an export from the order book to check it against — every quotation and every confirmed order over four months — and I could stop arguing and go and look.

The reason this matters is structural, not local. Google's click-through conversion window maxes out at [ninety days, with thirty as the default](https://support.google.com/google-ads/answer/3123169?hl=en&ref=livain.com). For anything with a long sales cycle, the outcome you care about lands outside the window the optimiser can see, by construction. The platform is not lying to you. It is answering a question about your website, and you are reading it as a question about your business.

### The matching is the work

I went in expecting an email join and got a ladder of five. Email first, which is clean and covers most of the business enquiries. Then full name, tried in both orders, whole words only. Then surname plus postcode, which is how you catch the ones who typed their name differently on the website than the sales desk typed it into the ERP. Then company by email domain, with free-mail providers excluded or every Gmail address in the file collapses into one customer. Then company by name.

Each rung down the ladder is less certain and needs tighter rules. Company-by-name matched on partial strings until "Meier Gartenbau" started hitting four unrelated firms called Meier; it now needs at least two words to agree. A reverse substring test — looking for the ERP name inside the website name — had to come out entirely, because it generates confident nonsense. And because the free-text reference field contains building-site project numbers, the number-based matching needed digit boundaries or it matched a project code to a document number.

None of this is exotic. It is textbook [entity resolution](https://www.rudderstack.com/blog/what-is-entity-resolution/?ref=livain.com), and the standard advice applies: run deterministic matches first, then fuzzier passes, and [keep the match tier recorded on every row](https://dataladder.com/fuzzy-matching-101/?ref=livain.com) so you can see later which conclusions rest on the weakest evidence. Mine does. Email, name, surname-plus-postcode and the two company tiers are separate columns, not one boolean.

> If you can't say which rung of the ladder a match came from, you don't have attribution. You have a number with a good story attached.

### Count the firm, not the person

Halfway through, the owner made a call that simplified everything and that I would not have reached on my own. He did not care whether a buyer was an existing customer, and he did not care whether the person who filled in the form was the person who signed. What counted was whether the *company* had touched the website, the price list or a campaign at all.

That is a commercially reasonable definition and it changed the result materially. Landscaping firms download a price list under one employee's name and order six weeks later through a colleague. On a person-level match, that is a miss. On a company-level match, it is exactly the thing marketing was supposed to do.

The lesson generalises past this client: the unit of attribution is a business decision, not a technical one. Ask before you build, or you will build the wrong join and defend it.

### Young cohorts have to be aged, or your newest month looks like your worst

The lag distribution in this data is the most useful thing in it. Median time from enquiry to confirmed order is eight days. Roughly three quarters land inside three weeks. The tail runs out past eighty days.

Which means a raw conversion rate on last month's enquiries is not a low number — it is an unfinished one. So the model weights each enquiry by how much of the empirical lag curve has actually elapsed, and puts a Wilson interval around the result instead of reporting a single confident percentage. The newest cohort stops looking like a collapse and starts looking like what it is: incomplete.

Get this wrong and you will cut the channel that is still maturing. I have [argued before that you should test whether a dip is a signal](https://www.livain.com/blog/test-whether-a-dip-is-a-signal-before-hunting-for-a-bug/) before you act on it. Cohort immaturity is the most common fake dip there is.

### What the order book actually said

Just over one enquiry in five had become a confirmed order inside the window. That ratio is not the finding, though. The finding is how differently the enquiry types behaved.

The cart-based quotation request — where someone assembles what they want and asks for a price — converted several times better than anything else, both into quotations and into orders. The price-list download, the thing that produces the most volume and looks best in the ad account, produced quotations rarely and, in four months, no orders at all. And paid search generated a healthy stack of enquiries with nothing behind them in the order book over the same period, while organic carried the orders.

That last sentence would be an enormous claim off a single quarter, so I am not making it. The paid campaigns have been live for weeks, not quarters, and against an eighty-day tail that is no verdict. What it does justify is the next move: feed the matched outcomes back as offline conversions so the optimiser is bidding toward orders rather than form fills, which is what [offline conversion import](https://support.google.com/google-ads/answer/13321563?hl=en&ref=livain.com) exists for. Bidding on the download is bidding on the thing that does not convert.

Also worth saying out loud: one single quotation in the matched set is large enough to move the total on its own. A median is a safer thing to manage by than a mean when one building site can be worth more than a year of the rest.

### The uncomfortable part

Four months of marketing work was defensible before this join existed. It was just not provable. The export turned "we generated a lot of enquiries" into a number with an order attached to it, and that cuts both ways — it also named a channel and a lead type that are not earning their place yet.

I would rather have the number that argues with me. The alternative is [reporting enquiry value as if it were revenue](https://www.livain.com/blog/client-performance-dashboard-enquiry-value-not-revenue/) and hoping nobody joins the two files.

Attribution does not get real until it touches the order book. Go and ask for the export.

### Sources & further reading

**External**  
[About conversion windows](https://support.google.com/google-ads/answer/3123169?hl=en&ref=livain.com) (Google Ads Help)  
[Fix discrepancies and errors in offline conversion imports](https://support.google.com/google-ads/answer/13321563?hl=en&ref=livain.com) (Google Ads Help)  
[What is entity resolution? Use cases and best practices](https://www.rudderstack.com/blog/what-is-entity-resolution/?ref=livain.com) (RudderStack)  
[Fuzzy matching 101: the complete guide to accurate data matching](https://dataladder.com/fuzzy-matching-101/?ref=livain.com) (Data Ladder)

**Related posts**  
[A price-list download is not a lead](https://www.livain.com/blog/price-list-download-is-not-a-lead-long-lead-time-attribution/)  
[The client dashboard that reports enquiry value, not revenue](https://www.livain.com/blog/client-performance-dashboard-enquiry-value-not-revenue/)  
[Scaling a Google Ads budget while attribution is broken](https://www.livain.com/blog/scaling-google-ads-budget-while-attribution-is-broken/)  
[Test whether a dip is a signal before hunting for a bug](https://www.livain.com/blog/test-whether-a-dip-is-a-signal-before-hunting-for-a-bug/)