ReplyLabs
FeaturesPricingCompareFAQUse casesBlogHelpSetup
Sign inGet started free
Get started

Product

  • Install
  • Features
  • Pricing
  • Compare
  • Roadmap

Resources

  • Use cases
  • Blog
  • Glossary
  • Cost calculator

Support

  • Setup Guide
  • Help Center
  • Contact Support
  • Report an Issue
  • Feature Requests

Company

  • Opt Out of Testing

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie list
  • Subprocessors

Empra Consultancy LTD
hello@replylabs.io

ReplyLabs|PrivacyTermsCookiesSubprocessors

© 2026 Empra Consultancy LTD. All rights reserved.

All articles
Blog

Scrape, Summarise, Score: Multi-Step Enrichment in Sheets

Running enrichment one step at a time wastes money on rows that already failed. How to chain steps in a spreadsheet so each one only sees rows that qualify.

By ReplyLabs · 5 min read · 5 September 2026

On this page
  • What running steps separately actually costs
  • Order the chain cheap to expensive
  • Failures need to propagate, not vanish
  • Doing this in a spreadsheet
  • A chain worth copying
  • Related reading

The short answer.

  • Real enrichment is a chain: scrape, then summarise, then score, then write.
  • Run the steps independently and each one processes rows the previous step already ruled out. That is where the budget goes.
  • The expensive step should be last and narrowest, not first and widest.
  • Chaining also fixes the reporting problem: you can see which step lost a row.

Almost nobody needs one enrichment operation. The actual job is a sequence, and it usually looks like this:

  1. Take a list of company domains.
  2. Read each website and pull out what the company does.
  3. Decide whether it fits the profile you sell to.
  4. For the ones that fit, write an opening line that references something specific.

Each step depends on the one before it. Step 4 is meaningless without step 2, and running it on a company you have already disqualified is money spent on a row you will delete.

What running steps separately actually costs

Take a list of 1,000 domains and a realistic set of outcomes. Some sites will not be readable, for the ordinary reasons: the page is JavaScript-rendered, the domain is parked, the site blocks automated requests, the company has folded. Say 200 rows come back empty. Then the scoring step disqualifies 400 of the 800 that worked, because they are the wrong size or the wrong sector.

StepRows if run independentlyRows if chained
1. Scrape the website1,0001,000
2. Summarise1,000800
3. Score against ICP1,000800
4. Write the opening line1,000400
Total row-operations4,0003,000

A quarter of the work removed, and the removed quarter is concentrated in step 4, which is the most expensive step because it is the longest prompt. The saving in money is larger than the saving in row count.

There is a second saving that does not appear in the table. Every one of those 200 unreadable rows produces a summary of nothing, a score based on that summary, and an opening line referencing a company nobody could read anything about. That is not just wasted spend, it is output you have to find and remove, and if you do not find it, it goes out under your name.

Order the chain cheap to expensive

The rule that does most of the work: the narrower the step, the later it goes; the cheaper the step, the earlier.

A common mistake is to personalise first because it is the interesting part, then filter afterwards. Reversing that is usually a fifty percent cut in the expensive step's volume, and the personalisation gets better as well, because it is now only running on companies that actually fit.

A reasonable default order:

  1. Cheap structural filters first, and free ones before paid ones. Discard obvious non-fits on data you already have.
  2. Fetch, once per row, and pull everything you need from that one fetch.
  3. Classify or score, with a short prompt and a constrained output.
  4. Generate, long prompt, only on survivors.
  5. Verify contact details last, on the rows you will actually contact, because verification is priced per check and there is no reason to verify an address you are not going to write to.

That last one is worth stating plainly because it is commonly done first out of habit.

Failures need to propagate, not vanish

The hard part of chaining is not the sequence, it is what happens when a step fails for one row.

A blank cell is ambiguous in a way that gets expensive. It can mean the fetch failed, or the page was readable but did not mention what you asked for, or the model returned nothing, or the row was skipped because an earlier step disqualified it. Those four have completely different remedies, and once the value is a blank cell they are indistinguishable.

What a chain should preserve for each row:

  • Which step it stopped at, so you know where the loss happened.
  • Why, at least to the level of blocked, empty, timed out, or disqualified.
  • Whether it is retryable. A timeout is worth another attempt; a parked domain never will be.

With that, re-running failures is a targeted operation on the rows that could benefit. Without it, the only options are re-running everything or accepting the holes.

Doing this in a spreadsheet

You can approximate the whole thing natively with helper columns: one column per step, an IF guarding each so it only computes when the previous column has a value, and a manual selection at each stage.

It works, and it degrades in a predictable way. The guards get intricate. Adding 200 new rows means re-running each stage in order and remembering which ranges you have already done. Retrying only the failures means sorting, copying to a scratch sheet, running, and pasting back. None of these are hard; all of them are the kind of manual step that gets skipped under time pressure, which is exactly when a half-run list goes out.

Flows in ReplyLabs is the version of this that does not need supervising: you define the steps once against your columns, each step runs only on rows that qualified in the previous one, failures carry a reason, and re-running failures is a single action rather than a spreadsheet manoeuvre. The Flows guide covers how the steps are wired together.

A chain worth copying

For an outbound list built from company domains, this ordering holds up:

  1. Filter on what you already have: sector, region, obvious exclusions. Free.
  2. Read the website once, extracting the positioning, the apparent size, and any signal you care about, in a single pass.
  3. Score against your profile with a short prompt returning a number and a one-line reason. The reason is what makes a bad score debuggable.
  4. Cut below your threshold. This is the step people skip.
  5. Write the personalised line for survivors only.
  6. Verify the email addresses of the rows that made it this far.

Six steps, and the two expensive ones run on the smallest lists in the chain.

Related reading

  • ICP scoring for outbound lists
  • Waterfall enrichment, and when to fall back
  • Personalised cold email at scale
  • Lead enrichment in Google Sheets

Frequently asked questions

Running several dependent operations over the same list in sequence, where each step reads the output of the previous one. A typical chain is: scrape the company website, summarise what the company does, score it against your ICP, then write a personalised opening line for the rows that scored well.
On this page
  • What running steps separately actually costs
  • Order the chain cheap to expensive
  • Failures need to propagate, not vanish
  • Doing this in a spreadsheet
  • A chain worth copying
  • Related reading

Keep reading

All articles
Blog

Why Enrichment Coverage Is Never 100%, and What Is Normal

Blog

What 1,000 Enriched Leads Actually Cost, Line by Line

Blog

How Many Rows Can You Run AI On in Google Sheets?

Try it on your own list

ReplyLabs runs from a sidebar inside Google Sheets. Start free with $20 credit, no card needed.

Get started free