The workflow before#
Capital One's search advertising runs at a scale few marketers deal with: millions of keywords spread across thousands of Google Ads campaigns. Before this project, the marketing team judged those keywords with third-party bidding tools and qualitative reviews. Last-click attribution gave credit to whatever ad a customer clicked just before applying and ignored everything that came earlier. Analysts reviewed performance after the fact and adjusted bids by hand, often days or weeks behind the data. At that scale, nobody could say with confidence which spend to scale and which to cut. Strong keywords stayed underfunded, weak ones kept spending, and budget conversations leaned on judgment more than evidence.
What we built#
We built a model that estimates what each keyword is actually worth, then let it steer the bids. It predicts the conversion value of every keyword from years of history, and a bid engine raises or lowers bids on those predictions within strict daily limits. The marketing team can see every move the system makes and why it made it.
A value score for every keyword
The attribution model is a neural network trained on more than 3 years of keyword performance joined with conversion and CRM data. It looks past the last click to the whole path to an account, and it predicts conversion value per keyword with about 85% accuracy. We trained one model across all campaigns rather than one per campaign, so keywords with thin data borrow signal from patterns in the rest of the account.
Bid changes with guardrails
Predictions feed a bid adjustment engine that works through the Google Ads API. Strong keywords get higher bids and weak ones get lower bids, but no bid moves more than 25% up or 30% down in a day, and the engine won't act until a keyword has enough data. We made the limits asymmetric on purpose: trimming waste quickly is cheap, while overbidding on a weak signal is not.
Human review for campaigns that keep missing
Campaigns that keep falling short of their benchmarks get flagged for a person to review, and they're paused only if they don't recover. We kept people in that decision because pausing a campaign is a bigger call than nudging a bid. The marketing team knows things the model doesn't, like a product launch or a seasonal push.
Every move on a dashboard
Dashboards and alerts show keyword performance, prediction accuracy and each bid change the system makes. A marketer who wants to know why a bid dropped overnight can find the answer without asking a data scientist. That visibility is what lets the team trust the engine to run every day.
How we delivered it
We built the data foundation first: hourly pulls from Google Ads, plus conversion, web analytics and CRM data synced into Amazon Redshift with automated quality checks. The model came next, validated on time-based splits so it was always tested on weeks it hadn't seen. Before handing bids to the engine, we ran A/B tests and holdout groups that compared model-driven bidding with manual bidding, so the team could judge the change on its own results.
Before and after#
| Measure | Before | After |
|---|---|---|
| Attribution | Last click, from third-party tools | Keyword-level, multi-touch model |
| Bid changes | Manual, after the fact | Automated daily within set limits |
| Data freshness | Days to weeks | Hourly Google Ads extracts |
| Underperforming campaigns | Judged case by case | Flagged against benchmarks for review |
What's next#
The same pipelines and model serving pattern can extend to display, social and video. That would put budget decisions across every paid channel on the same evidence as search, and let the team move money between channels on predicted value instead of each channel's own reporting.







