Every day, emails the next few leads in your sheet a random article with a short AI note, and comes back to each after a set gap.

UsesClaudeGmailGoogle Sheets

Drip helpful articles to your leads

ScheduleRun every day at 09:00.Run every day at 09:00.
ValuesSet spreadsheetUrl to blank.Set spreadsheetUrl to blank.
ValuesSet leadsTabName to blank.Set leadsTabName to blank.
ValuesSet articlesTabName to blank.Set articlesTabName to blank.
ValuesSet sentTabName to blank.Set sentTabName to blank.
ValuesSet senderContext to blank.Set senderContext to blank.
ValuesSet signOff to blank.Set signOff to blank.
ValuesSet optOutLine to If you would rather not get these, just reply and say so..Set optOutLine to If you would rather not get these, just reply and say so..
ValuesSet leadsPerDay to 5.Set leadsPerDay to 5.
ValuesSet daysBetweenEmails to 7.Set daysBetweenEmails to 7.
ValuesSet secondsBetweenEmails to 5.Set secondsBetweenEmails to 5.
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as leadsRead.Read the rows of spreadsheetUrl. Save it as leadsRead.
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as articlesRead.Read the rows of spreadsheetUrl. Save it as articlesRead.
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as sentRead.Read the rows of spreadsheetUrl. Save it as sentRead.
Decisions & LoopsIf articlesRead.count is 0If articlesRead.count is 0
Yes
Decisions & LoopsStop and report a problem: The articles tab is empty. Add at least one row with a Title and a URL, and optionally a Summary, then run again.Stop and report a problem: The articles tab is empty. Add at least one row with a Title and a URL, and optionally a Summary, then run again.
No
No steps
Decisions & LoopsIf leadsRead.count is 0If leadsRead.count is 0
Yes
Decisions & LoopsFinish the run: The leads tab has no rows under its header, so there is nobody to email today.Finish the run: The leads tab has no rows under its header, so there is nobody to email today.
No
No steps
CodeRun Python code on leads, articles, sent, now_text, leads_per_day, and days_between and save it as plan.Run Python code on leads, articles, sent, now_text, leads_per_day, and days_between and save it as plan.
Decisions & LoopsFor each note in plan.notes:For each note in plan.notes:
ValuesShow in the output: note.Show in the output: note.
Decisions & LoopsIf plan.articles is 0If plan.articles is 0
Yes
Decisions & LoopsStop and report a problem: None of the rows on the articles tab could be used - each needs a Title and a URL starting with http. Nothing was sent.Stop and report a problem: None of the rows on the articles tab could be used - each needs a Title and a URL starting with http. Nothing was sent.
No
No steps
Decisions & LoopsIf plan.picks is emptyIf plan.picks is empty
Yes
Decisions & LoopsFinish the run: No lead is due an article today. Nothing was sent.Finish the run: No lead is due an article today. Nothing was sent.
No
No steps
ValuesSet sentCount to 0.Set sentCount to 0.
ValuesSet skippedCount to 0.Set skippedCount to 0.
ValuesSet failedCount to 0.Set failedCount to 0.
Decisions & LoopsFor each pick in plan.picks:For each pick in plan.picks:
ValuesSet leadEmail to pick.email.Set leadEmail to pick.email.
ValuesSet articleTitle to pick.title.Set articleTitle to pick.title.
ValuesSet articleUrl to pick.url.Set articleUrl to pick.url.
ValuesSet emailBody to blank.Set emailBody to blank.
Decisions & LoopsIf a step below fails, save the error as writeErrorIf a step below fails, save the error as writeError
Try
ClaudeClaudeAsk Claude: 'You are writing a short, friendly email on behalf of a person to one of their sales leads, sharing a link the person thinks the lead will find useful. It is a helpful touchpoint between conversations - not a pitch, and not a 'just checking in' message.Ask Claude: 'You are writing a short, friendly email on behalf of a person to one of their sales leads, sharing a link the person thinks the lead will find useful. It is a helpful touchpoint between conversations - not a pitch, and not a 'just checking in' message. Use ONLY the facts below. Do not invent anything about the lead, their company or the article beyond what is written here. Never imply you have spoken or met before - no 'as we discussed', no 'following up on our call'. Do not add pricing, offers or deadlines. About the sender and what they do: senderContext The lead: pick.facts The article to share: pick.article_facts Write the email body only, as plain text with no subject line, no markdown and no sign-off (the sender's own sign-off is added afterwards). Start with 'Hi ' followed by the lead's first name and a comma. Then two or three short paragraphs: one line on why this seemed worth sending them, what it covers in a sentence or two drawn only from the summary, and the link on its own line exactly as written above. Close with one light sentence that leaves the door open, with no pressure. Keep the whole thing under 150 words.'. Save it as written. Maximum response length: 600
TextTrim written.response_text and save it as emailBody.Trim written.response_text and save it as emailBody.
On error
ValuesShow in the output: Could not write the note for leadEmail: writeError as text.Show in the output: Could not write the note for leadEmail: writeError as text.
Decisions & LoopsIf emailBody is emptyIf emailBody is empty
Yes
ValuesShow in the output: No note came back for leadEmail, so they are left for the next run.Show in the output: No note came back for leadEmail, so they are left for the next run.
ValuesAdd 1 to skippedCount.Add 1 to skippedCount.
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
Decisions & LoopsIf emailBody doesn't contain articleUrlIf emailBody doesn't contain articleUrl
Yes
ValuesChange emailBody to emailBodyChange emailBody to emailBody articleUrl.
No
No steps
ValuesChange emailBody to emailBodyChange emailBody to emailBody signOff optOutLine.
Decisions & LoopsIf sentCount is greater than 0If sentCount is greater than 0
Yes
Decisions & LoopsWait for secondsBetweenEmails seconds.Wait for secondsBetweenEmails seconds.
No
No steps
ValuesSet recorded to false.Set recorded to false.
Decisions & LoopsIf a step below fails, save the error as recordErrorIf a step below fails, save the error as recordError
Try
Google SheetsGoogle SheetsAdd a row to sentTabName in spreadsheetUrl.Add a row to sentTabName in spreadsheetUrl.
ValuesChange recorded to true.Change recorded to true.
On error
ValuesShow in the output: Could not record the send for leadEmail on the '@sentTabName' tab, so nothing was sent to them: recordError as text.Show in the output: Could not record the send for leadEmail on the '@sentTabName' tab, so nothing was sent to them: recordError as text.
Decisions & LoopsIf recorded is noIf recorded is no
Yes
ValuesAdd 1 to skippedCount.Add 1 to skippedCount.
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
Decisions & LoopsIf a step below fails, save the error as sendErrorIf a step below fails, save the error as sendError
Try
GmailGmailSend an email to leadEmail.Send an email to leadEmail. Subject: articleTitleemailBody
ValuesAdd 1 to sentCount.Add 1 to sentCount.
ValuesShow in the output: Sent '@articleTitle' to leadEmail.Show in the output: Sent '@articleTitle' to leadEmail.
On error
ValuesAdd 1 to failedCount.Add 1 to failedCount.
ValuesShow in the output: Recorded but could not send '@articleTitle' to leadEmail: sendError as text - delete that row from the '@sentTabName' tab to try again next run.Show in the output: Recorded but could not send '@articleTitle' to leadEmail: sendError as text - delete that row from the '@sentTabName' tab to try again next run.
ValuesShow in the output: Sent sentCount as text article email(s), failedCount as text failed to send, skipped skippedCount as text, out of the length of plan.picks as text lead(s) in today's batch.Show in the output: Sent sentCount as text article email(s), failedCount as text failed to send, skipped skippedCount as text, out of the length of plan.picks as text lead(s) in today's batch.