New to Attio?Get 10% off when you sign up through Craftt.Try Attio free →
← All case studies

Almost a year fighting HubSpot. Rebuilt on Attio in one week.

Captivate Talent is a US executive search firm placing GTM and RevOps leaders. They had spent close to a year, and a lot of money, trying to make HubSpot model a business where the sale ends at signature and the real work starts there. We rebuilt it on Attio in one week: five objects, two independent pipelines on one deal, seven integrations, nightly rollups, and AI agents that can each write one thing and nothing else. Then we stayed through the first two months of real use, fixing what live data exposed and building the leadership dashboard their weekly meeting now runs on.

Full rebuild + support

Engagement

1 week

Live on Attio

1,180

Deals, one per search

$14.3M

Fees reconstructed

387

Placements recovered

7

Integrations live

6

AI agents

The problem.

HubSpot had been fought for almost a year, and the mismatch was structural rather than a configuration problem. In HubSpot the deal is the sale, and it ends when the money is agreed. In executive search the sale ends at signature, and the work that earns the fee, sourcing, shortlist, offer, start date, the guarantee period, all happens afterwards on the same record.

So one search has to carry two independent states at once. No amount of pipeline configuration made that clean. Nor did the second rule of the business: a client who hires you three times is three deals under one company, not one account with a bigger number on it.

The money had the same problem. Three different figures were all being called revenue: the fee actually earned, the contract value on paper, and the estimate on unsigned work. Added together they produce $31.6M for a business that has booked $14.3M.

And the history lived in the ATS, not the CRM. A search is only created in the ATS once a contract is signed, so 51 of 58 live searches had no CRM record at all. Signed clients were sitting in the pipeline looking like prospects.

Objectives.

  • Model one search as one deal, so a repeat client stacks deals under one company instead of overwriting an account.
  • Run the sales ladder and the delivery ladder on the same record without either overwriting the other.
  • Name one field as the real revenue number, and make every report use it.
  • Pull the ATS, the e-signature tool, the booking tool, the website form and the event platform into Attio, so nothing is retyped.
  • Reconstruct the history that never made it out of HubSpot: placements, fees, referrers, regions.
  • Put AI to work with hard write limits, so no agent can ever overwrite a number a human chose.
  • Get the weekly leadership numbers out of the spreadsheets two team leads were building by hand.

The data model.

Five objects. That is the whole model, and the discipline is as much in what is deliberately kept out of it.

Deals

One search: one role, for one client, at one time. Carries both ladders, the three money fields kept strictly apart, the guarantee clock, a Business Type that says whether the search is a new client or an expansion, and a Replaces Deal link so a free replacement search points back at the original without booking the same fee twice.

Companies

Client, prospect, investor or fractional partner, with ICP fit and the recurring friction that makes an account hard to work. Lifetime fees, placements, searches won and open searches are calculated nightly, never typed.

People

Hiring managers, VC partners, event guests, and 537 placement alumni: 314 found hiding in a HubSpot tag, 194 recreated from the ATS. Candidate names never cross from the ATS. Someone placed years ago who is now a hiring manager is the warmest lead in the business, and is now a filter rather than a memory.

Referral Partners

The 83 sources that send business, with referrals sent, revenue influenced and last referral date rolled up from the deals they touched.

Events

48 dinners, conferences and happy hours, with guest lists split into registered, checked in and declined, and a flag for whether Captivate hosted or simply attended.

The two ladders.

The idea the whole model turns on. A deal moves along both at once, and Closed Won does not mean finished. It means sold.

Deal Stage — are they going to pay us

Interest Expressed, Discovery Call, Proposal and Fee Agreed, Contract Sent, then Closed Won or Closed Lost. This ladder stops the moment the contract is signed.

Delivery Status — how is the work going

Search live, Shortlist out, Offer out, Placed, In guarantee, Complete, plus Replacement in progress, Failed to place and On hold. This ladder only starts once the deal is Closed Won.

What feeds the workspace.

Seven systems write into Attio. Attio writes back to none of them, and the ATS in particular is never touched.

Stardex (the ATS)

A candidate marked Hired fires a webhook that writes the placement start date, the real fee and the guarantee end onto the matching deal. A nightly pull creates deals for live searches that had none, which is how 51 signed clients stopped looking like prospects.

HelloSign

Polled nightly rather than webhooked, deliberately, so nothing had to be authorised on anyone else's side to turn it on. A contract out for signature moves the deal to Contract Sent, and creates the deal when the client is known but the role has none. The first run found nine contracts out for signature. The team believed there were four.

Typeform

A website enquiry creates the company, the person and a deal at Interest Expressed. The answers are stored as raw text first; classifying them into fields is a separate step that can be rerun without ever losing what the person actually wrote.

Luma

Event guest lists sync onto Event records: registered, checked in, declined. When a third-party Luma app started writing shell events alongside our sync, we traced it, merged what only the shells held onto the real records, and took Events from 85 back to 48 without a single attendee link lost.

Calendly

A booked intro call moves the deal to Intro Call Scheduled and sets the owner from the host. It filters on the event type's ID, never its name: across the company, 127 bookings carried 28 different event names over 12 hosts, and recruiters name candidate interviews after clients. The first version keyed on less and turned candidate calls into empty deals. It was caught, cleaned up and filtered within a day.

Gmail and Google Calendar

Attio's native sync gives every record a real last-contact date, which is what turns "this account has gone quiet" from a feeling into a filter.

Metaview

After a discovery call, the transcript fills role title, target salary, fee percentage, practice area, search type and the referrer, and attaches the summary as a note.

Five agents, each with a hard limit.

Every agent may write one defined thing and nothing else. An agent that can edit anything will eventually edit something wrong, and then nobody can tell which field a human chose and which one a robot guessed.

Discovery-call fill

Fills what the call agreed, and never overwrites a field that already holds a value. If the call contradicts the record, it says so in the note and leaves the record alone. A human who typed a number had a reason; a transcript is a rough draft.

Search summary

Turns ATS pipeline state into one client-readable line on the deal: "1 at offer, 3 interviewing and 30 sourced." No candidate name crosses over. If it cannot verify a count it writes "over 30" rather than asserting a number, because a missing summary reads as a quiet pipeline.

Weekly report

Monday 7am New York into Slack: fees booked, placements, forecast, which referral partners drove them, what is stuck. It never invents a number, never posts twice, and still posts on a quiet week, because silence looks like a broken job.

Client prep brief

On a new enquiry it reads the account, its whole history and the web, then writes one note with 6 to 8 discovery questions. Every claim carries its source, anything it could not establish is written as "unknown", and it changes no field.

Nightly rollups

Recalculates every derived number in the workspace, and refuses to write if it reads suspiciously few records, so a half-loaded night looks broken instead of looking like a bad week.

What runs by itself.

Roughly a dozen workflows. The rule for each one was the same: fire forward, never guess backwards, and post to the team's pipeline channel when something changes that a person should know about.

Guarantee clock

Daily. When a placement's guarantee lapses, delivery moves to Complete, the fee to Invoiced, and the channel hears about it. It checks delivery status as well as the date, because seven live searches still carried a guarantee date from an earlier placement.

Monday search-health sweep

Live searches with no movement are flagged At risk and posted. The automation can say that a search is stuck. Only a recruiter can say why, so the reason stays a human field.

Deal gone quiet

A 14-day nudge driven by the company's last email, because Attio keeps interaction dates on people and companies, not on deals, and a migrated deal's creation date is the migration day.

Closed Won broadcast

Every win posts to the channel, except a replacement search, which would otherwise announce itself as new business.

Replacement searches

When a hired candidate is later rejected in the ATS, the gap in days decides. Inside the 90-day guarantee a replacement deal opens with the work on it and the money left on the original. Outside it, Chris gets a task instead.

Investor becomes a partner

Setting a company's type to Investor or Fractional Partner creates and links the Referral Partner record, so the VC-intro attribution model is fed without anyone remembering to do it.

After go-live: what two months of real use changed

A migration is tested by the first quarter of live data, not by the handover call. These are the things that only showed up once the team was working in it, and what we did about each.

The reports read a 93% win rate, and it was the migration talking

In September Chris flagged a closed-won rate that could not be true. The cause was structural: Attio stamps every imported record with the day it was imported, so any report built on creation date saw the whole HubSpot history as if it had happened in one day, inside the current quarter.

Danielle and Chris chose not to reconstruct the legacy chronology. Every report now counts only deals created after go-live, HubSpot stays open for lookups until November, and Q4 2026 is the first quarter that reports honestly. It was their decision, and the right one: four rounds of historical cleanup is enough.

The obvious filter, created after the go-live date, was still wrong by nine deals. Our own backfill scripts had kept writing historical placements for a week after the load days, and eight of them were already won. So the cohort is cut by who created the record, a person or a live workflow, not by when. That moved the win rate by five points, and it is the only cut that survived every backfill.

A leadership dashboard their meeting actually uses

The numbers are reviewed in a weekly leadership meeting, and two team leads were still building them by hand in spreadsheets: deals won and lost, time to hire, expansion, deal sources, quarterly with a weekly cut. We built a small dashboard on Vercel that reads Attio live and lets leadership change filters during the meeting instead of after it.

Funnels are cumulative, so a deal that skipped a stage still counts through the stages it cleared. Current-state cards ignore the date filter, because a search that is live today is live today whenever it started. Blank values are hidden by default and labelled when shown.

New client or expansion, settled as a definition first

Business Type had four values and the team could not tell two of them apart. Danielle settled it as a reporting rule: New client is a company's first search, Expansion is every search after it, with no time limit, and replacements stay off the field entirely.

The nightly job had been measuring first win, not first search, so a second search at a company that had never won came back as a new client. We fixed the logic, repaired 66 deals and archived the value nobody used. On the corrected numbers, more than half of all won fees come from clients who came back.

What we were honest about

Some fields are empty on purpose. 10,412 imported contacts have no owner because nobody at Captivate has ever emailed or met them, and there is nothing true to put there. 1,151 companies have no region because they have no country on file. A blank is visible. A guess looks like data.

One agent needs data only the client can give. The placement-announcement agent drafts an email to the funds backing a newly placed client, and never sends. It depends on an Investors link on each client, which is best filled by hand at contract stage, because early-stage cap tables are exactly where enrichment tools are weakest.

The three money words.

Fees booked all time is $14.3M. Deal value on paper is $17.3M. The pipeline estimate is a guess on unsigned work. All three describe the same business, so a report showing $31.6M is wrong. Naming them and forbidding their addition removed the single most common cause of a wrong number in front of a client. Replacement searches are excluded from every fee total, because the money stayed on the original deal, but they still count in open searches, since that work is real and eats capacity while earning nothing.

Results.

  • One search, one deal. A repeat client stacks searches under one company instead of overwriting a single account.
  • Two independent pipelines on one record, sales to signature and delivery from signature, so Closed Won can never be mistaken for finished.
  • $14.3M of historical fees, 387 placements and 537 placement alumni reconstructed from the ATS and the HubSpot export. The fee total matches the ATS to the dollar.
  • 51 signed searches that had no CRM record now sit in delivery where they belong, and live searches on the board went from 35 to 81.
  • Region rebuilt from country across 1,026 companies, and coverage moved onto the deal where the decision actually belongs.
  • Seven integrations live, with candidate data deliberately kept out of the CRM. What lands on a deal is something a client could read over your shoulder.
  • Contact owner filled on 5,122 people from who actually knows them, taking owned contacts from 2,593 to 7,715.
  • Weekly leadership numbers moved off hand-built spreadsheets onto a live dashboard, with a cohort cut that excludes every migrated and backfilled record.
  • Nightly rollups that refuse to run on a partial read, and scripts that are dry-run by default, because more than one definition was wrong the first time and only the dry run caught it.
  • A full runbook handed over: field glossary, report definitions, workflow catalogue, integration map, and a practical guide written so a new joiner can use the system on day one.
“George is an absolute GEM - I am so glad we found him. We'd been struggling for almost a year, trying to get HubSpot set up to do what we wanted it to do (and spending way too much money in the process). George set it all up within two weeks beyond what we could have dreamt. He's an incredible data architect and will think through your unique business use case and the best way Attio can bring that to life. I couldn't recommend him more!!”

Danielle Parker

Captivate Talent

Ready when you are.

Book a call and we will tell you honestly whether this is worth doing, or start with the free 48-hour audit and decide afterwards.