Daily ZoomInfo company enrichment to Google Sheets

Every morning at 6am, fill in industry, headcount, revenue, HQ, and tech stack for every pending company in your Google Sheet using ZoomInfo.

Deterministic Code
ZoomInfoGoogle SheetsOperationsSalesData SyncLead Enrichment

Build a code workflow that runs every day at 6am on a cron trigger and enriches a Google Sheet of company domains using ZoomInfo.

Trigger: cron, daily at 06:00 in the user's local timezone.

Step 1. Use the Google Sheets Get Values operation to read the 'To Enrich' tab of a configured spreadsheet. The tab has at least these columns: a 'domain' column with company domains (e.g. acme.com) and a 'status' column. Read the full used range so we can locate rows by their row number.

Step 2. Filter the rows in code to those where status is empty, null, or equal to the string 'pending' (case-insensitive). Keep track of each domain's 1-based row number in the sheet, because we will need it to write the enriched values back to the same row.

Step 3. Group the pending domains into batches of 25. ZoomInfo's Enrich Companies operation accepts up to 25 records per request, so this batch size is a hard ceiling, not a suggestion. If there are 0 pending rows, log a no-op and exit cleanly.

Step 4. For each batch, call ZoomInfo's Enrich Companies operation with the batch of domains as the match input and the following outputFields list: industry (or primaryIndustry), employeeCount, revenue, hqAddress (street, city, state, country, zip), phone, website, and the technographic fields covering technologies used and tech categories. Include any standard company identity fields the downstream sheet wants (company name, ZoomInfo company ID). Re-runs against companies enriched in the last 12 months are credit-free, so we do not need extra dedup logic beyond the status column.

Step 5. For each enrichment response, build a Google Sheets Batch Update Values payload that writes back to the same row in the 'To Enrich' tab:

  • If ZoomInfo returned a match: write the enriched columns (company name, industry, employee count, revenue, HQ city/state/country, phone, website, technologies), stamp an 'enriched_at' column with today's date in ISO format, and set the status column to 'enriched'.

  • If ZoomInfo returned no match for the domain: leave the enrichment columns blank, stamp the 'enriched_at' column with today's date, and set the status column to 'no_match' so the row is skipped on the next run.

Use a single Batch Update Values call per ZoomInfo batch (not per row) so we stay well under Google Sheets' write rate limit. Use USER_ENTERED as the value input option so numbers and dates render correctly.

Step 6. Handle ZoomInfo errors gracefully: on a 429 rate-limit, retry the batch with exponential backoff. On a 401 or 403, fail the run with a clear error. On any other batch-level failure, log the failing batch's domains and continue processing remaining batches so one bad batch does not stall the whole run.

Configuration the user should provide at setup time: the spreadsheet ID, the sheet/tab name (default 'To Enrich'), the name of the domain column, the name of the status column, and the names of the enriched output columns. Default the timezone to America/New_York if not specified.

Integrations: zoominfo (Enrich Companies), google-sheets (Get Values, Batch Update Values).

Additional information

What does this prompt do?
  • Reads the To Enrich tab of your Google Sheet every morning and picks up any row whose status is blank or pending.
  • Sends those domains to ZoomInfo in batches of 25 and pulls back industry, employee count, revenue, headquarters, phone, website, and the technologies they use.
  • Writes the enriched fields back to the matching row, stamps it with the run date, and marks the status as enriched so it never re-runs against the same company.
  • Marks domains ZoomInfo has no match for as no_match, so your list keeps moving instead of getting stuck on dead entries.
What do I need to use this?
  • A ZoomInfo account with API access enabled and enrichment credits available.
  • A Google Sheet with a tab named To Enrich, a column of company domains, and a status column.
  • A Google account that can read and write to that sheet.
How can I customize it?
  • Change the run time, run every few hours, or run on weekdays only.
  • Add or remove enrichment fields, for example funding stage, LinkedIn URL, or specific technologies your sales team cares about.
  • Point it at a different sheet, tab, or status column if your CRM ops team uses a different naming convention.

Frequently asked questions

How many companies can this enrich per run?
As many as you want. ZoomInfo accepts up to 25 companies per enrichment request, and the workflow keeps batching until your pending list is empty. A few thousand domains in one morning is normal.
Will it burn through my ZoomInfo credits if I re-run it?
No. Once a row is marked enriched it gets skipped on the next run, and ZoomInfo does not charge again for companies you have already pulled in the last 12 months. Re-runs are cheap.
What happens to domains ZoomInfo has never heard of?
They get a no_match status so the workflow stops trying them. You can review that list, fix typos, or replace them with a different identifier and re-queue.
Can I use this with a different spreadsheet layout?
Yes. Tell the workflow which tab to read, which column has the domains, and which column tracks status. You can also rename or reorder the enriched output columns.
Do I need to be a developer to set this up?
No. Connect your ZoomInfo account and your Google account, point the workflow at your sheet, and it runs on the schedule you pick.

Stop hand-researching every company on your list.

Connect ZoomInfo and Google Sheets once, and Geni keeps your enrichment queue moving every morning before the team logs on.