We build dashboards, MTA models, Media Mix Models, and AI systems that tell Marketing teams what drives growth.
Companies we have worked with:
Multi-touch attribution, and media mix modeling built so it can be explained to cross functional teams, not just marketing.
The essential layer beneath it all: data models, pipelines, and dashboards that are built to load fast without breaking the bank.
LLM workflows and agentic pipelines that verify results and minimize hallucinations saving you hundereds of hours each year.
Thirty minutes, no charge. Tell us what you're trying to measure or automate and we'll see if we can help.
Pick a time on the calendar. Prefer email? timshil@gmail.com
Every multi-touch attribution model contains a decision you made before you saw any data. That doesn't make it useless — it makes it a different tool than the one most teams think they bought.
We've built multi-touch attribution models from scratch, in SQL, for companies that badly needed them. We still think the single most expensive mistake in marketing analytics is treating the output of one as a spending instruction.
Here's the problem in one line: attribution tells you which touchpoints were present on the path to a conversion. It does not tell you which ones caused it. Those are different questions, and only one of them answers "what happens if I turn this off?"
This piece is the explanation we give clients before we build anything: what MTA measures, why the credit rule is an assumption rather than a result, what the published evidence says about how far off attribution can be, and the three-model structure we put in place instead.
An MTA model does three things. It stitches events into user- or account-level paths, orders those paths in time, and then divides credit for the conversion across the touchpoints on the path according to a rule you choose.
Notice that only the first two steps involve measurement. The third step — the part everyone quotes in budget meetings — is arithmetic applied to a convention. The model is a very good description of co-occurrence: what tends to appear alongside conversions. Co-occurrence and causation come apart badly whenever a channel is good at reaching people who were already going to convert, which is precisely what the best-performing channels in most accounts are doing.
Three terms are worth pinning down before anyone argues about a number:
Almost every unproductive attribution argument we've walked into was two people using the first word and meaning the second.
When you build an MTA model, you pick how weighted credit gets distributed across touchpoints. The standard options, and what each one structurally favors:
Every one of those is a convention. None of them is measured. Which means the model's conclusions are partly downstream of an assumption you made in week one. Branded search is the classic trap: it sits at the end of nearly every path, so almost any credit rule flatters it, and it is very often the channel with the least incremental value in the entire portfolio.
That isn't a hunch. In a large-scale field experiment at eBay published in Econometrica (Blake, Nosko and Tadelis, 2015), researchers turned branded search advertising off across matched markets and found that the overwhelming majority of the traffic it had been "buying" arrived anyway through organic results. Measured returns were near zero to negative in the short run — against an attribution report that had been crediting those ads generously for years.
Write your credit rule down before you look at the results, and share it with whoever consumes the dashboard. If it changes later, that's fine — but a rule change and a performance change should never be indistinguishable in the same chart.
The most useful study on this ran inside Facebook and was published in Marketing Science (Gordon, Zettelmeyer, Bhargava and Chapsky, 2019). The authors took 15 large-scale randomized controlled advertising experiments, then re-analyzed the same underlying data using the observational methods that attribution and lookback-window reporting rely on, and compared the answers.
The observational estimates frequently missed the experimental benchmark by large multiples, and they missed in both directions — sometimes dramatically overstating lift, sometimes understating it. The errors were not a fixed bias you could calibrate away with a correction factor. That's the finding that matters operationally: you cannot look at an attributed ROAS and reason reliably about the incremental one without an experiment somewhere in the system.
A second paper worth knowing is Lewis and Rao's "The Unfavorable Economics of Measuring the Returns to Advertising" (Quarterly Journal of Economics, 2015). Using a set of large digital experiments, they showed that the variance in individual purchase behavior is so much larger than typical advertising effects that even campaigns reaching millions of people often cannot statistically distinguish a very good ROI from a very bad one. This is the real reason so many tests come back "inconclusive," and it is a sample-size problem, not an analysis problem.
MTA depends on observing the same person across sites, apps and sessions. That capability has been eroding for years, and the erosion is asymmetric across channels, which quietly distorts comparisons:
Add the platform-reporting problem on top. Meta's default conversion window is 7-day click / 1-day view; Google Ads search defaults to a 30-day click window with data-driven attribution. Each platform counts a conversion it saw, in its own window, with no visibility into the others. Sum platform-reported conversions across your channels and you will routinely exceed the number of conversions your warehouse actually recorded. That gap isn't a bug in anyone's pixel — it's what happens when several systems each take full credit for shared outcomes.
The setup we recommend to clients isn't one model. It's three, each pointed at the decision it can actually answer.
1. Multi-touch attribution answers diagnostic questions about the path. Which campaigns show up early in deals that eventually close? Which leads are sales actually contacting? Where do accounts stall? At Chronosphere we built a custom in-house MTA in SQL, and its real value wasn't budget allocation — it was giving the team the first honest picture of how many qualified leads marketing generated by campaign and quarter, and what share of those leads sales ever touched. That gap turned out to be the story. MTA is a process-diagnosis tool, and it is excellent at that job.
2. Media mix modeling answers allocation questions across channels. MMM is a time-series regression on aggregate spend and outcomes — typically two to three years of weekly data — with controls for seasonality, pricing, promotions and macro conditions. It needs no user-level tracking at all, which is exactly why it has come back into fashion: Meta open-sourced Robyn in 2020 and Google released Meridian in 2025, both Bayesian MMM frameworks aimed at teams who lost their cross-site identifiers.
Two mechanics do most of the work in an MMM, and they're worth understanding even if you never fit one yourself:
MMM is also the only one of the three that can put a TV dollar and a TikTok dollar on the same axis, and the only one that handles channels with no click at all.
3. Experiments answer causal questions. Geo holdouts, matched-market tests and clean A/B tests are the only way to actually observe what happens when spend goes away. The tooling is mature and mostly free: Google's CausalImpact package (Brodersen et al., 2015) uses Bayesian structural time series to build a synthetic control from untreated markets, and Meta's open-source GeoLift does matched-market selection and analysis in the same spirit. Experiments are slower and cover less ground, and they're the only thing on this list that produces truth rather than an estimate. Use them to calibrate the other two.
The three fit together as a loop: experiments produce ground truth on a few channels, that ground truth calibrates the MMM's priors and validates its coefficients, the MMM sets the allocation, and MTA diagnoses what's happening inside the funnel between campaigns and closed revenue.
A good measurement stack usually starts by making your reported performance look worse. Incrementality testing tends to reveal that some of your best-looking channels were harvesting demand that would have converted anyway — the eBay result, repeated at smaller scale in most accounts we've examined. That's not a failure of the analysis, it's the whole point of it, but it does mean somebody has to be ready to defend the finding internally.
That's the actual job. The regression is a weekend. Getting an organization to change how it spends money based on what the regression said is the work.
Vivid Labs builds measurement systems — attribution, media mix modeling, and incrementality testing — for growth teams that have to prove the number. Book a free 30-minute call.
A document extraction demo takes an afternoon. The other 80% is grounding, redaction, retries, and a constrained output space — and that 80% is the entire difference between a prototype and something a compliance team will use.
I recently built an agentic document processing system at Google that pulled compliance and business requirements out of data center documentation in a dozen inconsistent formats. The model call is maybe fifteen lines. Everything that made the system usable sat around it.
These are the four things I'd build again on any extraction pipeline, in roughly the order they save you.
An LLM that invents a compliance requirement is worse than no tool at all, because a plausible fabrication costs a reviewer more time than a blank page. So the pipeline runs verbatim verification: every extracted requirement is checked back against the source text it claims to come from. If the span isn't there, the requirement doesn't pass.
The important design decision is where that check sits. A confidence score displayed next to a result is a report — a human has to notice it and act. A verification step that blocks unverified output from ever reaching a reviewer is a gate. Only the gate actually changes what people see, and only the gate lets you say something true about the output as a whole.
The corollary: extract aggressively, then filter. It's much easier to discard an over-extracted requirement that fails verification than to discover months later that the model quietly skipped a clause. Tune for recall at the model, and let the verifier handle precision.
PII redaction has to happen locally, on your server, before the content ever leaves for the model API. Not in post-processing, not by asking the model nicely to ignore it. Regex over the source text is unglamorous and it works, and the review conversation about your architecture goes very differently when the answer to "what personal data reaches the vendor?" is "none, structurally."
Same category: API keys live in server-side environment variables and nowhere else. Every client-side key becomes a public key the moment someone opens dev tools. This is obvious, and it is still the single most common finding I see in AI prototypes that grew into products.
Anything processing documents at volume will hit HTTP 429s. A pipeline that treats a rate limit as a failure will silently drop work, and you'll find out from a gap in the data weeks later.
Exponential backoff handles it, but backoff alone isn't enough — you need jitter. Without random jitter, every retry from a batch reconverges on the same moment and hammers the API in synchronized waves, which is how a small hiccup becomes an outage of your own making. I used async-retry for this, but the library matters far less than the fact that someone decided retries were part of the design rather than something to bolt on after the first incident.
Decide explicitly what's retryable. A 429 or a 503 is. A 400 from a malformed request is not, and retrying it just burns quota while hiding a bug.
Free-text output from a model is a dead end for anything downstream. Two documents describing the same requirement will produce two different phrasings, and now you can't count, diff, or join anything.
So the pipeline maps every validated requirement onto a controlled vocabulary — predefined industry domains and common control IDs — and persists the structured result to BigQuery. The moment output lands in a warehouse with a stable schema, ordinary analytics work again. You can ask which controls appear most often, what changed between document versions, and where coverage is thin. None of that is possible against a pile of prose.
Every one of these is really the same move: take something the model does probabilistically and put a deterministic system around it. Regex for redaction. String matching for verification. A fixed vocabulary for output. Explicit retry rules for failure.
The model does the part that genuinely requires judgment — reading messy human documents and understanding what's being required. Everything else is conventional engineering, and it should be, because that's the part you need to be able to reason about when someone asks whether the output can be trusted.
If you're evaluating an LLM feature and the demo looks great, the useful question isn't about the prompt. It's: what happens when the model is wrong, and how would anyone know?
Tim Shilstone builds production AI systems and measurement infrastructure through Vivid Labs. Book a free 30-minute call.