CascadeGTM Playbooks

The Data Quality Playbook

Every GTM play you run sits on top of your data. If the data is dirty, the signal is noise and your automation just amplifies the mistake faster. This is a plug-and-play workflow — Apollo to acquire, Google Sheets to hold, Claude to clean — that gives you a self-correcting contact and company database you can stand up today. The prompts and the steps are below. Copy them and run.

By CascadeGTM, GTM strategy and revenue engineering. Published June 2026. The first in a plug-and-play playbook series that extends Buy, Build, or Vibe Code.

Data quality is the least glamorous part of GTM engineering and the one that decides whether everything downstream actually works. A scoring model trained on stale titles scores noise. A routing rule keyed on a misspelled domain routes to nobody. A sequence personalized from the wrong company name does worse than no sequence at all — it tells the buyer you did not look. The expensive tools sitting on top of your stack are only ever as good as the rows underneath them.

So before any of the interesting plays — attribution, ABM, intent — there is this one. It is unglamorous, and it compounds. Clean data never announces itself; it just quietly makes every other number true. Here is the call on what to buy, what to build, and the exact workflow I run.

What to buy, what to build

Acquire

Apollo

Companies, contacts, and firmographics from $49–79/mo. Pulling raw records is a solved problem — do not build a scraper to re-solve it.

Call: Buy
Store

Google Sheets

A sheet is a perfectly good CRM for one operator: queryable, scriptable, shareable. Graduate to a real CRM the day a second person needs it.

Call: Buy (free)
Engine

Claude

The cleaning, the normalization, the judgment — this is where a GTM engineer earns the title. You build this part with prompts, not code.

Call: Build
The workflow

Four stages, run as a waterfall: Acquire raw records, Normalize them to one shape, Dedupe against what you already have, then Validate & enrich so every row is trustworthy and labeled. Each stage hands clean output to the next.

Stage 1 — Acquire

Apollo to Sheets. The goal of this stage is volume of raw records, not clean ones. Cleaning comes next.

  1. In Apollo, build a saved search for your ICP. For GTM Ops work that is growth-stage companies, Series A–D, with an open RevOps or GTM-engineering req or a CRO/CMO who started in the last 90 days.
  2. Export the people view with first name, last name, title, company, domain, LinkedIn URL and the firmographic fields. Apollo Basic exports manually; the API on Professional lets you schedule it.
  3. Paste the export into a Sheet tab named raw. Never hand-edit raw. Every later stage reads from it and writes to a clean tab, so you can always re-run from source without losing work.

Stage 2 — Normalize

Raw exports are inconsistent by nature. “VP, Revenue Operations,” “VP RevOps,” and “V.P. Rev Ops” are the same job. “Acme, Inc.” and “Acme Incorporated” are the same company. Normalize to one shape first, or every match you attempt later quietly fails. Paste your raw rows into this prompt; write the output to a clean tab.

Normalize prompt · Claude
You are a GTM data normalization engine. I will paste rows from a raw contact export, tab-separated, with these columns:
first_name  last_name  raw_title  raw_company  domain  linkedin_url

For each input row, return exactly one row, tab-separated, in the SAME order, with these columns:
first_name  last_name  canonical_title  segment  company_clean  domain  seniority

Rules:
- canonical_title: the standard form of the role (e.g. "VP, Revenue Operations"). Expand abbreviations, fix casing, drop punctuation noise.
- segment: choose exactly one of: GTM Ops Leaders | Sales Leadership | Marketing Leadership | Growth & Marketplace | Client Success | Finance & Founder. Map by what the role owns, not the literal words.
- company_clean: the common company name. Remove legal suffixes (Inc, LLC, Ltd) and trailing punctuation.
- domain: lowercase root domain only (acme.com, never www.acme.com or a path).
- seniority: one of C-level | VP | Head/Director | IC.

Return only the data rows. No header, no commentary, no code block. Preserve input order exactly.

Rows:
[PASTE YOUR RAW ROWS HERE]

Stage 3 — Dedupe

Dedupe on a stable key. For people that is lowercase email when you have it, otherwise lowercase first + last + domain. For companies it is the root domain. Build the key in Sheets, flag exact collisions with conditional formatting, then let Claude resolve the near-matches a formula will always miss.

Sheets · dedupe key + flag
=LOWER(TRIM(IF(E2<>"", E2, A2 & B2 & F2)))

# E = email, A = first_name, B = last_name, F = domain
# Then flag duplicates: Format -> Conditional formatting -> Custom formula:
#   =COUNTIF($G$2:$G, $G2) > 1

The formula catches exact duplicates. The typos, nicknames, and subsidiaries it cannot. Hand those to Claude.

Dedupe prompt · near matches
Here are contact rows that share no exact key but may be the same person or company (typos, nicknames, subsidiaries, formatting drift). Group any rows that point to the same real-world entity. For each group tell me which row to KEEP (most complete, most senior title, freshest source) and which to DROP.

Return, tab-separated, one line per dropped row:
keep_row_id  drop_row_id  reason

If a row has no duplicate, omit it. No commentary.

Rows:
[PASTE SUSPECTED NEAR-DUPLICATES, INCLUDING A row_id COLUMN]

Stage 4 — Validate & enrich

The last pass turns clean rows into trustworthy, labeled rows. It flags anything that looks wrong — a “CFO” on a personal Gmail address, a title that does not match its company — confirms the segment, and writes the one-line “why now” your outreach will lean on. Crucially, it is told to invent nothing: the why-now is grounded only in the trigger you already captured.

Validate & enrich prompt · Claude
You are validating a cleaned GTM contact list before it drives outreach. For each row, return one row, tab-separated:
row_id  valid  flag_reason  segment_confirmed  why_now

- valid: yes/no. Say no if the row is internally inconsistent: a free-mail domain (gmail, outlook) on a senior title, a title that contradicts the company, or obvious test data.
- flag_reason: one short phrase, or blank if valid.
- segment_confirmed: re-affirm or correct the segment, from: GTM Ops Leaders | Sales Leadership | Marketing Leadership | Growth & Marketplace | Client Success | Finance & Founder.
- why_now: one sentence a human could actually send, grounded ONLY in the trigger fields provided. Invent nothing. If the trigger is weak or stale, write "no strong reason".

Columns provided:
row_id  first_name  last_name  canonical_title  segment  company_clean  domain  trigger_type  trigger_date

Rows:
[PASTE CLEAN ROWS]

Make it run on its own

Data quality is not a one-time cleanup, it is a standing process. Pick the cadence that matches your budget.

  1. Manual, free. Once a week, re-export from Apollo into raw, run the three prompts in order, paste the results into clean. Twenty minutes, and your database is current.
  2. Scheduled, Apollo Professional + Apps Script. A Google Apps Script time-trigger pulls the Apollo API into raw nightly; a second function sends the three prompts to the Claude API and writes clean. Now the database refreshes itself while you sleep.
Where this plugs in

This clean, labeled table is exactly what the Prospecting Engine reads. The trigger_type and trigger_date you validate here are what its priority logic ranks on. Clean data in, a ranked, human-approved queue out.

What good looks like

That is the whole foundation. It is not the play that wins the meeting — it is the one that makes every other play honest. Build it once, keep it running, and the attribution, ABM, and intent playbooks that follow finally have something true to stand on.

Want the engine that runs on this data?

The Prospecting Engine turns a clean, labeled list like this into a ranked, human-approved outreach queue — mock data, nothing sent.

Open the demo Work Together