# Research ~500 target accounts a month with an AI assistant and Google Sheets

> Replace the account-research columns you'd build in Clay with batched, cited web research in Claude or ChatGPT, a strict JSON output schema, a scoring rubric and a 10% hallucination spot-check. It does not replace verified contact data — you still need Apollo, ZoomInfo or similar for emails and phones.

- Outcome: Each month, turn a list of ~500 target companies into a qualified, cited, de-duplicated account list with a fit score and a personalisation angle for the best ones.
- Replaces: Clay (partial)
- Uses: Claude (optional) — Web search / Research mode with citations to research each batch and return JSON.; ChatGPT (optional) — Alternative: web search or deep research with citations to research each batch.; Google Workspace — Google Sheets as the master account list, de-dup formulas and QA log.; Apollo.io (optional) — Verified business emails/phones for Tier A accounts only. Any licensed contact-data provider works (ZoomInfo, etc.).
- Extra monthly cost: $0 — $0 extra if you already pay for Claude or ChatGPT with web search and already have a contact-data source. Usage limits on research features vary by plan, so heavy months may hit caps. Contact data is NOT included: if Clay was also your email-finding tool, budget for a contact-data provider separately.
- Difficulty: moderate; skill: basic; setup: 2–3 hours (rubric, prompt tuning on 2 test batches, sheet setup)
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/prospect-research-with-ai-assistant

## Good fit for
- Founders, SDRs and small sales teams researching tens to a few hundred accounts per week
- Account-based outreach where a cited 'why now' matters more than list size
- Teams that used Clay mainly for AI research and scoring columns, not for waterfall contact enrichment
- Anyone who can spend a few hours a week on batched research and spot-checks

## Not a fit for
- Teams that need verified emails, mobile numbers or firmographics at scale — that's a contact-data product, not an AI assistant
- Thousands of accounts per month or fully automated enrichment on a trigger — manual batching doesn't scale; consider an API pipeline or keep Clay
- Workflows that depend on scraping LinkedIn or other sites whose terms forbid automated collection
- Anyone not willing to spot-check sources — unchecked AI research will contain fabricated or misattributed facts

## Before
A Clay workbook imports a company list, runs enrichment and AI research columns per row (company summary, recent news, hiring signals, a scoring formula, an AI-written first line) and pushes results to a CRM or sequencer. It's fast and automated but billed in credits/actions, and the bill grows with every column and re-run.

## After
A Google Sheet holds the master list. Each working session you paste 10–25 new, de-duplicated companies into a saved research prompt in Claude or ChatGPT with web search on. The assistant returns strict JSON (one object per company, every claim with a source URL), which you paste into the sheet. Formulas flag duplicates and score totals; you open the sources for 10% of rows (and every Tier A) before trusting the batch. Only Tier A accounts go to Apollo/ZoomInfo for verified contacts.

## Steps

### 1. Write your rubric before you research anything

Copy the **Qualification rubric** artifact and replace the bracketed descriptions with your real ICP: core industries, employee sweet spot, the signals that actually predicted past wins.

Test it on **10 past customers and 10 lost deals**. If the rubric doesn't rank most past customers above the losses, fix the rubric now — no prompt will rescue a vague ICP.

Keep `reachability` partly human: warm paths come from *your* CRM and network, not from the AI.

### 2. Set up the master sheet

Create a Google Sheet with tabs **Input**, **Accounts**, **Manual**, **QA**.

- **Input:** `Company name | Domain | Normalised domain | Already researched?` with the formulas from the *De-duplication and QA* artifact.
- **Accounts:** one column per field in the JSON schema, plus `Batch ID`, `Researched on`, `QA result`, `Owner`, `Status`.
- Use **Data → Data validation** dropdowns for `tier` and `Status` (`New / Checked / Contacted / Disqualified`).

To paste JSON into columns, ask the assistant to also output the batch as **TSV** in a second code block (the batch prompt below does this), then paste into the first empty row of Accounts.

### 3. Run research in batches of 10–25

In Claude (turn on **web search**, or use **Research** on Pro/Max/Team/Enterprise) or ChatGPT (web search or **deep research**), paste the **Batch account research** prompt with 10–25 companies.

Why small batches:
- Quality drops and the model starts skipping or merging companies in long lists.
- Research modes consume plan limits faster; Anthropic notes Research uses the same limits as normal chats but can use them up faster.
- A bad batch of 20 is cheap to re-run; a bad batch of 200 isn't.

**Throughput reality:** 500 accounts ≈ 25 batches of 20. At 15–30 minutes per batch including QA, budget **8–20 hours a month**. Save the prompt in a Claude Project or ChatGPT Project/custom GPT so every batch uses identical instructions.

### 4. Validate structure, de-duplicate, then spot-check sources

Follow the *De-duplication and QA* artifact for every batch:

1. **Structure:** row count in = out; `fit_total` = sum of scores; every row has ≥1 source; no emails/phones.
2. **Identity:** if `resolved_domain` ≠ input domain, the model may have researched a namesake — move to **Manual**.
3. **Spot-check 10%** (minimum 3 rows, plus *every* Tier A): open each source URL and confirm the claim is on the page and the date matches. Log PASS/FAIL in **QA**.
4. If more than 1 in 10 fails, re-run the batch through the **Verify claims** prompt or redo it — don't fix rows by hand and trust the rest.

The rule *“no URL, no claim”* is what makes this usable: an uncited signal is capped at 1 point by the rubric.

### 5. Get contact data the compliant way — only for Tier A

An AI assistant **does not provide verified contact data**. Emails it 'finds' are often guessed patterns. For Tier A accounts only:

- Look up the buyer in **Apollo, ZoomInfo or another licensed provider**, or use contact details the company publishes for business enquiries.
- **Do not scrape LinkedIn.** LinkedIn's User Agreement (section 8.2) prohibits scraping or copying profiles and using bots or unauthorised automated methods. Read profiles manually if you must; don't automate it.
- **GDPR (EU/UK contacts):** document your lawful basis (usually legitimate interests) and give the Article 14 notice — who you are, why you have their data, where it came from, their rights — **at first contact** at the latest.
- **CAN-SPAM (US):** applies to B2B email too. Accurate headers and subject, a postal address, a clear opt-out honoured within 10 business days. Other countries (e.g. Canada's CASL) can be stricter — check where your recipients are.

### 6. Write openers from cited signals and close the loop

Use the **Personalisation from cited signals** prompt on Tier A rows only. It must quote the signal and URL it used, so you can check it in seconds.

After a month, compare reply and meeting rates by tier. If Tier B converts like Tier A, your rubric is too strict; if Tier A doesn't convert, re-weight `need_signal` and `timing`. Then decide what to cancel: if you only used Clay's research columns, downgrade it; if you also relied on its contact waterfall, keep or replace that part with a contact-data subscription.

## Prompts

### Batch account research (strict JSON)
Research 10–25 companies with citations and score them against your rubric.

```text
You are a B2B research analyst. Use web search. Research each company below for a seller of {{our_offer}} whose ideal customer is: {{icp_description}}.

Companies (name, domain):
{{company_list}}

Scoring rubric (score each 0–3):
{{rubric}}

Rules:
1. Every factual claim must come from a page you actually opened. Put its URL in source_url / sources. If you cannot find a source, write "unknown" and add the gap to `unknowns`. Never guess employee counts, funding or dates.
2. Prefer the company's own site, press releases, job boards and reputable news from the last 12 months. Today is {{today}}; ignore signals older than 18 months.
3. If a name is ambiguous, research the company at the given domain; set match_confidence accordingly. If you can't confirm it's the same company, use "low" or "not_found" and don't score it.
4. Do NOT output personal email addresses, phone numbers or home locations. Do not use LinkedIn content obtained by scraping.
5. reachability: score only 2 (buyer role publicly identifiable) or 1 (unclear); I'll add warm paths myself.
6. fit_total must equal the sum of fit_scores. Tier: A 11–15 with need_signal ≥2; B 7–10; C 3–6; otherwise disqualified with a reason.

Output exactly two code blocks and nothing else:
(a) a JSON array that validates against this schema:
{{json_schema}}
(b) the same rows as TSV with a header row, columns in schema order, signals flattened as "type: claim (date) URL" joined by " | ".
Return one object per input company, in input order, even if not found.
```

### Verify claims (second pass)
Have the assistant re-check a batch whose spot-check failed, claim by claim.

```text
Act as a fact-checker. For each row in the JSON below, open every source_url and check whether the page explicitly supports the claim, for the right company and date.

{{batch_json}}

Return a table with columns: input_name | claim | source_url | verdict (SUPPORTED / NOT FOUND ON PAGE / WRONG COMPANY / WRONG DATE / PAGE UNAVAILABLE) | corrected claim with new URL, or "remove".
Then return the corrected JSON array with unsupported claims removed, fit_scores lowered where a removed claim was the basis (cap uncited criteria at 1), fit_total and tier recomputed. Do not add new claims without a URL.
```

### Personalisation from cited signals
Draft a first line for Tier A accounts that a human can verify in seconds.

```text
Write a first line for a cold email from {{sender_name}} at {{our_company}} to the {{buyer_role}} at {{company_name}}.

Use ONLY these cited signals:
{{signals_with_urls}}

Our relevant proof point: {{proof_point}}

Rules: max 30 words; reference exactly one signal factually (no flattery, no 'I noticed', no invented details); no claims about the person. Give 3 options, and under each write the signal and URL it relies on.
```

## Templates and scripts

### JSON output schema for a research batch (schema)

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "AccountResearchBatch",
  "type": "array",
  "items": {
    "type": "object",
    "additionalProperties": false,
    "required": ["input_name", "input_domain", "resolved_domain", "match_confidence",
                 "what_they_do", "industry", "hq_country", "employee_range",
                 "signals", "fit_scores", "fit_total", "tier", "personalization_hook",
                 "unknowns", "sources"],
    "properties": {
      "input_name":       { "type": "string", "description": "Exactly as given in the input list" },
      "input_domain":     { "type": "string" },
      "resolved_domain":  { "type": "string", "description": "Domain of the company actually researched. Empty if not found." },
      "match_confidence": { "enum": ["high", "medium", "low", "not_found"] },
      "what_they_do":     { "type": "string", "maxLength": 300, "description": "One or two plain sentences" },
      "industry":         { "type": "string" },
      "hq_country":       { "type": "string", "description": "ISO country name or 'unknown'" },
      "employee_range":   { "enum": ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001-5000", "5000+", "unknown"] },
      "signals": {
        "type": "array", "maxItems": 5,
        "items": {
          "type": "object", "additionalProperties": false,
          "required": ["type", "claim", "date", "source_url"],
          "properties": {
            "type":       { "enum": ["hiring", "funding", "leadership_change", "product_launch", "expansion", "tech_stack", "partnership", "other"] },
            "claim":      { "type": "string", "maxLength": 200 },
            "date":       { "type": "string", "description": "YYYY-MM or YYYY-MM-DD; 'unknown' if not stated" },
            "source_url": { "type": "string", "format": "uri" }
          }
        }
      },
      "fit_scores": {
        "type": "object", "additionalProperties": false,
        "required": ["icp_industry", "size", "need_signal", "timing", "reachability"],
        "properties": {
          "icp_industry": { "type": "integer", "minimum": 0, "maximum": 3 },
          "size":         { "type": "integer", "minimum": 0, "maximum": 3 },
          "need_signal":  { "type": "integer", "minimum": 0, "maximum": 3 },
          "timing":       { "type": "integer", "minimum": 0, "maximum": 3 },
          "reachability": { "type": "integer", "minimum": 0, "maximum": 3 }
        }
      },
      "fit_total":   { "type": "integer", "minimum": 0, "maximum": 15 },
      "tier":        { "enum": ["A", "B", "C", "disqualified"] },
      "disqualify_reason": { "type": "string" },
      "personalization_hook": { "type": "string", "maxLength": 240, "description": "Must reference one of the cited signals" },
      "unknowns":    { "type": "array", "items": { "type": "string" } },
      "sources":     { "type": "array", "minItems": 1, "items": { "type": "string", "format": "uri" } }
    }
  }
}

NOTE: this schema intentionally has NO fields for personal email addresses or phone numbers.
Verified contact data comes from a contact-data provider, not from an AI assistant.
```

### Qualification rubric (0–15) (template)

```
QUALIFICATION RUBRIC — edit the descriptions to match YOUR ideal customer profile (ICP).
Score each criterion 0–3. Total 0–15. The AI proposes scores; a human confirms Tier A.

1. icp_industry
   3 = core target industry ([your core industries])
   2 = adjacent industry we have won before
   1 = plausible but no references
   0 = outside our market → disqualified

2. size  (employees, from the company's own site or a cited source)
   3 = inside our sweet spot (e.g. 51–500)
   2 = just outside (e.g. 20–50 or 501–1,000)
   1 = far outside but has a relevant division
   0 = unknown after research (do NOT guess)

3. need_signal  (evidence they have the problem we solve)
   3 = explicit, dated, cited signal in the last 6 months (job post for the role we replace, public complaint, initiative announced)
   2 = indirect signal (growth, new market, tech stack that implies the need)
   1 = generic fit only
   0 = signal suggests they've already solved it (e.g. announced a competitor)

4. timing
   3 = trigger event in the last 90 days (funding, new leader in the buyer role, expansion)
   2 = trigger event 3–12 months ago
   1 = none found
   0 = known freeze (layoffs, acquisition pending) — note it

5. reachability
   3 = we have a warm path (customer, investor, partner in common) — fill from YOUR records, not the AI
   2 = clear buyer role exists and is publicly identifiable
   1 = buyer role unclear
   0 = no way in found

TIERS
   A = 11–15 and need_signal ≥ 2 → human review, then contact-data lookup, then personal outreach
   B = 7–10 → nurture list / lighter-touch sequence
   C = 3–6 → park; re-check in 6 months
   disqualified = icp_industry 0, or a hard exclusion (existing customer, competitor, sanctioned country, under legal minimum size)

RULE: any score based on a claim without a source URL is capped at 1.
```

### De-duplication and QA checklist with Sheets formulas (checklist)

```
DE-DUPLICATION AND QA — run on every batch before it enters the master sheet

A. De-duplicate (Google Sheets, master tab "Accounts")
   1. Normalise the domain in a helper column (assume raw domain/URL in column B):
      =LOWER(REGEXREPLACE(REGEXREPLACE(TRIM(B2),"^(https?://)?(www\.)?",""),"[/?#].*$",""))
   2. Flag duplicates against everything already researched:
      =IF(COUNTIF($C$2:$C, C2)>1, "DUPLICATE", "")
   3. Before each run, remove input rows whose normalised domain already exists in Accounts
      (=ISNUMBER(MATCH(C2, Accounts!C:C, 0)) on the input tab). This avoids paying for the same research twice.
   4. Also check resolved_domain vs input_domain: if they differ, the AI may have researched a
      different company with a similar name → set status "CHECK MATCH".

B. Structural checks (instant, every row)
   [ ] JSON parsed without edits (if not, re-run the batch; do not hand-fix silently)
   [ ] Row count out = row count in
   [ ] fit_total equals the sum of fit_scores
   [ ] Every signal has a source_url; every row has ≥1 source
   [ ] No email addresses or phone numbers anywhere in the output (search for "@" and digit runs) — delete if present
   [ ] match_confidence "low"/"not_found" rows are moved to a Manual tab, not scored

C. Hallucination spot-check (10% of rows, minimum 3 per batch, ALWAYS include every Tier A)
   For each sampled row, open every source URL and confirm:
   [ ] The page loads and is about this company (not a namesake)
   [ ] The claim is actually stated on the page (not inferred)
   [ ] The date matches
   Record result in a "QA" column: PASS / FAIL + note.
   If >1 of 10 sampled rows FAIL → re-run the whole batch with the verification prompt; don't trust the rest.

D. Compliance gate before any outreach
   [ ] Contact details came from a licensed provider or the person's own published business contact page — not scraped from LinkedIn
   [ ] EU/UK contacts: lawful basis (usually legitimate interests) documented; GDPR Art. 14 notice given at first contact
   [ ] US commercial email: CAN-SPAM basics in the template (accurate From/subject, postal address, working opt-out honoured within 10 business days)
   [ ] Suppression list (unsubscribes, existing customers, competitors) applied
```

## Limitations
- No verified contact data: AI assistants don't maintain a B2B contact database. Emails they produce are often guessed patterns; use a licensed contact-data provider.
- Manual batching: 10–25 companies per run. 500 accounts a month is 25–50 runs and roughly 8–20 hours of human time, versus near-zero in an automated Clay table.
- Research quality depends on what's public. Private companies, small firms and non-English markets return many 'unknown' fields.
- AI research makes mistakes: namesake companies, outdated news presented as current and claims not actually on the cited page. The 10% spot-check reduces but doesn't eliminate this.
- Research features have plan-based usage limits that can change; a heavy month can hit them.
- No native CRM/sequencer push — results move by copy/paste or CSV import.

## Risks
- **reliability** (high): Hallucinated or misattributed facts can end up in outreach and damage credibility. Mitigation: no URL, no claim; spot-check 10% plus every Tier A; re-run failing batches.
- **compliance** (high): Outreach to people still triggers GDPR (EU/UK: lawful basis, Article 14 notice by first contact) and CAN-SPAM (US: applies to B2B; FTC lists penalties of up to $53,088 per violating email). Using the AI doesn't change who is the data controller — you are.
- **compliance** (medium): Scraping LinkedIn (directly or by asking an agent to) breaches LinkedIn's User Agreement section 8.2 and can get accounts restricted. Keep research to public web pages and licensed data.
- **sensitive_data** (low): Company lists and ICP notes are commercially sensitive. Use a business/team plan or check your consumer plan's training settings before pasting customer or pipeline data.
- **functionality_loss** (medium): You lose Clay's automation: scheduled refreshes, enrichment waterfalls across providers and pushes to CRM/sequencers.

## Verification checklist (run before cancelling)
- [ ] The rubric ranks at least 7 of 10 known past customers above at least 7 of 10 known lost/unfit deals in a back-test.
- [ ] Two full test batches (≥40 companies) came back as valid JSON with one row per input, in order, with no emails or phone numbers.
- [ ] Spot-check of those batches: at least 90% of sampled claims are SUPPORTED when you open the source URL; every Tier A row passed a full source check.
- [ ] Side-by-side on 25 accounts: the AI's tiering agrees with your existing Clay scoring (or a human's judgement) on at least 20.
- [ ] The de-dup formula catches a deliberately re-pasted batch (all rows flagged DUPLICATE) and normalises 'https://www.example.com/about' to 'example.com'.
- [ ] Contact data for Tier A accounts is coming from a licensed provider or published business contacts, and your outreach template includes the CAN-SPAM elements and (for EU/UK) an Article 14 notice.
- [ ] You timed a real month's workload (or a week × 4) and the hours are acceptable versus what you pay for Clay.

## Savings methodology
Savings = Clay subscription you can drop or downgrade − any extra spend (normally $0 if you already pay for Claude/ChatGPT with web search). Contact-data costs are excluded on both sides: if Clay was also your email finder, you need a contact-data subscription either way, so subtract that from the savings. Labour is the hidden cost: at 15–30 minutes per 10–25 companies, 500 accounts is roughly 8–20 hours a month — price your time before deciding.

Example (illustrative): A two-person outbound team that used a Clay Launch plan mainly for research and scoring columns on ~500 accounts a month. $167/mo → $0/mo. Assumptions: ILLUSTRATIVE: Clay's pricing page on 2026-10-13 showed $167/month as the Launch headline price but also lower 'starts at' prices and different figures in its FAQ, so we treat $167 as an example, not a verified price. Use your own invoice. They already pay for Claude or ChatGPT with web search; no new subscription. Contact data comes from an Apollo/ZoomInfo seat they already have; that cost is unchanged and excluded. 8–20 hours a month of research and QA time is not converted to dollars.

## Sources
- Clay pricing: https://www.clay.com/pricing (accessed 2026-10-13)
- Using Research on Claude: https://support.claude.com/en/articles/11088861-using-research-on-claude (accessed 2026-10-13)
- LinkedIn User Agreement: https://www.linkedin.com/legal/user-agreement (accessed 2026-10-13)
- FTC CAN-SPAM Act compliance guide: https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business (accessed 2026-10-13)
- GDPR Article 14: https://gdpr-info.eu/art-14-gdpr/ (accessed 2026-10-13)
- ChatGPT deep research FAQ: https://help.openai.com/en/articles/10500283-deep-research-faq (accessed 2026-10-13)
