Daily candidate import from Google Sheets to SourceWhale

Every weekday morning, new names from your sourcing sheet get added to the right outreach campaign, with every single one checked for duplicates first.

Deterministic Code
SourceWhaleGoogle SheetsHR & PeopleSalesData SyncEmail Automation
PromptCreate

Every weekday at 7am, load newly sourced candidates from my Google Sheets sourcing sheet into SourceWhale and enrol them into their outreach campaign, without ever adding the same person twice. Build this as a code workflow on a cron trigger.

Start by reading the sourcing sheet with the Google Sheets Get Values operation, pulling the whole data range in one pass using A1 notation (for example Sourcing!A2:H1000). The sheet holds one candidate per row, with columns for first name, last name, email, company, job title, LinkedIn URL, Campaign, and Status. There is no pagination to deal with: the requested range comes back in a single response.

Process only the rows that have an email address AND a blank Status cell. A row whose Status is already filled in was handled on an earlier run and must be skipped. A row with no email address must be left completely untouched with its Status still blank, so a person can fix the missing address by hand and the next run will pick it up.

For each row to process, look the person up in SourceWhale using Search Candidates, passing that row's email address. SourceWhale matches on a single identifying field, so dedupe on email only and never fall back to matching by name, since two different candidates can share a name. If the search returns a candidate, that person is already in SourceWhale: do not add them, and record Skipped duplicate for the row.

If the search returns nothing, create them with SourceWhale Add Candidates, mapping first name, last name, email, company, job title, and LinkedIn URL from the sheet columns. Add Candidates supports campaign enrolment directly, so enrol the candidate into the campaign named in that row's Campaign column as part of the same call rather than making a second request. At the start of the run, call List Campaigns once and build a case-insensitive lookup from campaign name to the identifier Add Candidates expects, then reuse that lookup for every row. If a row's Campaign name matches no campaign, treat the row as an error rather than adding the candidate with no campaign.

After each row is handled, write the result back to that same row with the Google Sheets Update Values operation, targeting only that row's Status cell and the timestamp cell beside it. Set Status to Added, Skipped duplicate, or Error, together with the time the row was processed. This write-back is what makes the workflow safe to run daily: it is the record that stops the same person being re-imported and re-emailed tomorrow.

Handle failures per row, not per run. If a lookup or an add fails for one candidate, mark that row Error with a short reason and the timestamp, then continue with the remaining rows so one bad row never blocks the import. Note that SourceWhale returns a 401 both for an invalid API key and for a key that lacks access, so do not treat a 401 as a transient failure worth retrying. Keep Google Sheets writes to roughly one per second to stay inside its per-user write quota.

What does this prompt do?

  • Reads your sourcing spreadsheet every weekday morning and picks up only the rows you have not imported yet
  • Checks each person's email against your existing SourceWhale contacts before doing anything, so nobody gets added or emailed twice
  • Adds genuinely new people with their name, company, job title and LinkedIn profile, and enrols them straight into the campaign named on their row
  • Writes the outcome back into the row as Added, Skipped duplicate or Error with a timestamp, so your sheet stays the record of what happened

What do I need to use this?

  • A SourceWhale account, with an admin on your team available to connect it
  • A Google account with edit access to your sourcing spreadsheet
  • A sheet with one person per row and columns for first name, last name, email, company, job title, LinkedIn URL, Campaign, and an empty Status column
  • The outreach campaigns you want people enrolled into already created in SourceWhale

How can I customize it?

  • Change the timing: it runs every weekday at 7am by default, but daily, twice a day, or once a week all work the same way
  • Point it at a different sheet, tab, or set of columns as your sourcing template evolves
  • Add your own rule for what counts as ready to import, such as only rows where a reviewer column says yes or a Campaign name is filled in

FAQs

Will this email the same person twice?
No. Before adding anyone, it looks up that exact email address in your SourceWhale contacts. If the person is already there, nothing is added and nothing is sent, and the row is marked Skipped duplicate. The status written back into the sheet also means tomorrow's run ignores that row entirely.
What happens to rows that have no email address?
They are left completely alone with a blank Status, so they stand out as needing attention. Once someone fills in the missing email address by hand, the next scheduled run picks the row up automatically.
Does it match people by name as well as email?
Matching is on email address only. SourceWhale looks people up by one identifying detail at a time, and email is the most reliable one, since two different candidates can easily share the same name and would otherwise be wrongly skipped.
What happens if one row fails?
That row is marked Error with a timestamp and the run carries on through the rest of the sheet, so a single bad row never blocks the import. To retry a failed row, just clear its Status cell before the next run.
Can I run it more than once a day?
Yes. Because every processed row gets a Status written back, re-running only ever picks up rows that are still blank. Running it hourly is just as safe as running it once each morning.

Related templates

Weekly Amazon S3 bucket security audit posted to Slack

Every Monday, check every S3 bucket for public exposure, missing encryption and weak backup settings, then get the risks ranked in Slack.

Amazon S3
Slack Bot
Google Sheets
Agentic Task
Turn procurement portal tenders into CRM deals each morning

Every weekday at 7am, sign in to the tender portals you track, filter new notices against your bid criteria, and open a deal for the ones worth chasing.

Anchor Browser
Google Sheets
HubSpot
+1
Agentic Task
Draft polite follow-ups for emails that never got a reply

Every weekday at 4pm, spot the threads that went quiet, stage a ready-to-send nudge in your mailbox, and get a ranked Slack recap.

Aurinko
Google Sheets
Slack Bot
Agentic Task
Flag VIP client emails in Zoho Mail and alert your team

Keep a spreadsheet of your most important senders, and every email from one gets labeled, posted to your team channel, and logged automatically.

Zoho Mail
Google Sheets
Slack Bot
Deterministic Code
Send Yotpo review requests when Shopify orders ship

The moment an order is fulfilled, we register it with Yotpo so the review request is timed off real delivery, and we log every sync so failures never go unnoticed.

Shopify
Yotpo
Google Sheets
Deterministic Code
Reconcile Shopify sales against Zoho Books every night

Every night at 11pm we compare the day's Shopify orders with your Zoho Books invoices and payments, and flag only what does not match.

Zoho Books
Shopify
Google Sheets
+1
Agentic Task

Stop re-importing the same candidates every morning.

Set this up once and your sourcing sheet loads itself into SourceWhale each weekday, with a duplicate check on every row and a written record of what happened.