Checks each new enquiry against who you sell to, sends good ones to the right rep in Slack with a reply drafted, and parks the rest.

UsesClaudeApolloGmailGoogle SheetsHubSpotSlackZeroBounce

Route every new sales enquiry to the right rep

ScheduleRun every 2 minutes.Run every 2 minutes.
ValuesSet whoYouSellTo to blank.Set whoYouSellTo to blank.
ValuesSet whoYouDoNotSellTo to blank.Set whoYouDoNotSellTo to blank.
ValuesSet spreadsheetUrl to blank.Set spreadsheetUrl to blank.
ValuesSet slackChannelId to blank.Set slackChannelId to blank.
ValuesSet bookingLink to blank.Set bookingLink to blank.
ValuesSet formNamesThatMeanTalkToSalesNow to Request a demo,Contact sales,Pricing enquiry.Set formNamesThatMeanTalkToSalesNow to Request a demo,Contact sales,Pricing enquiry.
ValuesSet replyMode to slack.Set replyMode to slack.
ValuesSet replyWithinMinutes to 5.Set replyWithinMinutes to 5.
ValuesSet loadedNewLeads to {status:,headers:[],rows:[],count:0}.Set loadedNewLeads to {status:,headers:[],rows:[],count:0}.
ValuesSet loadedAccounts to {status:,headers:[],rows:[],count:0}.Set loadedAccounts to {status:,headers:[],rows:[],count:0}.
ValuesSet loadedReps to {status:,headers:[],rows:[],count:0}.Set loadedReps to {status:,headers:[],rows:[],count:0}.
ValuesSet loadedLedger to {status:,headers:[],rows:[],count:0}.Set loadedLedger to {status:,headers:[],rows:[],count:0}.
Decisions & LoopsIf a step below fails, save the error as sheetErrorIf a step below fails, save the error as sheetError
Try
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as loadedNewLeads.Read the rows of spreadsheetUrl. Save it as loadedNewLeads.
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as loadedAccounts.Read the rows of spreadsheetUrl. Save it as loadedAccounts.
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as loadedReps.Read the rows of spreadsheetUrl. Save it as loadedReps.
Google SheetsGoogle SheetsRead the rows of spreadsheetUrl. Save it as loadedLedger.Read the rows of spreadsheetUrl. Save it as loadedLedger.
On error
Decisions & LoopsStop and report a problem: Could not read the lead spreadsheet. It needs four tabs named exactly 'New leads', 'Accounts', 'Reps' and 'Ledger', and the Google Sheets connection must have access to it. Run the 'Inbound lead workspace setup' template to build one correctly. The underlying error was: sheetError.message.Stop and report a problem: Could not read the lead spreadsheet. It needs four tabs named exactly 'New leads', 'Accounts', 'Reps' and 'Ledger', and the Google Sheets connection must have access to it. Run the 'Inbound lead workspace setup' template to build one correctly. The underlying error was: sheetError.message.
ValuesSet freeMailDomains to gmail.com,googlemail.com,yahoo.com,hotmail.com,outlook.com,live.com,aol.com,icloud.com,me.com,proton.me,protonmail.com,gmx.com,mail.com,yandex.com,zoho.com,hey.com.Set freeMailDomains to gmail.com,googlemail.com,yahoo.com,hotmail.com,outlook.com,live.com,aol.com,icloud.com,me.com,proton.me,protonmail.com,gmx.com,mail.com,yandex.com,zoho.com,hey.com.
ValuesSet throwawayDomains to mailinator.com,10minutemail.com,guerrillamail.com,tempmail.com,trashmail.com,yopmail.com,sharklasers.com,dispostable.com,maildrop.cc.Set throwawayDomains to mailinator.com,10minutemail.com,guerrillamail.com,tempmail.com,trashmail.com,yopmail.com,sharklasers.com,dispostable.com,maildrop.cc.
ValuesSet roleAddressPrefixes to info,sales,support,admin,contact,hello,help,noreply,no-reply,billing,office,team,marketing,careers,jobs,hr,press,legal,webmaster,postmaster.Set roleAddressPrefixes to info,sales,support,admin,contact,hello,help,noreply,no-reply,billing,office,team,marketing,careers,jobs,hr,press,legal,webmaster,postmaster.
Decisions & LoopsIf loadedNewLeads.rows isn't empty and loadedNewLeads.headers doesn't containโ€ฆIf loadedNewLeads.rows isn't empty and loadedNewLeads.headers doesn't containโ€ฆ
Yes
Decisions & LoopsStop and report a problem: The 'New leads' tab is missing required column headers. Row 1 must contain exactly these, spelled and capitalised this way: Submission ID, Form, Name, Email, Company, Message. Run the 'Inbound lead workspace setup' template to build the sheet correctly.Stop and report a problem: The 'New leads' tab is missing required column headers. Row 1 must contain exactly these, spelled and capitalised this way: Submission ID, Form, Name, Email, Company, Message. Run the 'Inbound lead workspace setup' template to build the sheet correctly.
No
No steps
Decisions & LoopsIf loadedLedger.headers doesn't contain Submission ID or loadedLedger.headersโ€ฆIf loadedLedger.headers doesn't contain Submission ID or loadedLedger.headersโ€ฆ
Yes
Decisions & LoopsStop and report a problem: The 'Ledger' tab needs its heading row before the first run: it is how the workflow knows which leads it has already handled. Row 1 must read, in this order: Submission ID, Processed At, Email, Domain, Company, Decision, Reason Code, Fit Tier, Intent Tier, Intent Class, Confidence, ICP Score, Routed To, Routed To Slack ID, Routing Rule, SLA Due, Claimed At, Next Touch At, Touches Sent, Evidence, Reasoning. The 'Inbound lead workspace setup' template writes it for you.Stop and report a problem: The 'Ledger' tab needs its heading row before the first run: it is how the workflow knows which leads it has already handled. Row 1 must read, in this order: Submission ID, Processed At, Email, Domain, Company, Decision, Reason Code, Fit Tier, Intent Tier, Intent Class, Confidence, ICP Score, Routed To, Routed To Slack ID, Routing Rule, SLA Due, Claimed At, Next Touch At, Touches Sent, Evidence, Reasoning. The 'Inbound lead workspace setup' template writes it for you.
No
No steps
ListsKeep each item in loadedNewLeads.rows where item["Submission ID"] isn't blank and item.Email contains @ and save it as leadsWithAnAddress.Keep each item in loadedNewLeads.rows where item["Submission ID"] isn't blank and item.Email contains @ and save it as leadsWithAnAddress.
ListsCompare leadsWithAnAddress with loadedLedger.rows, matching by Submission ID and save it as comparedWithLedger.Compare leadsWithAnAddress with loadedLedger.rows, matching by Submission ID and save it as comparedWithLedger.
ListsRemove duplicates of Submission ID from comparedWithLedger.only_in_first and save it as newLeads.Remove duplicates of Submission ID from comparedWithLedger.only_in_first and save it as newLeads.
ListsTake the first 10 items of newLeads and save it as leadsThisRun.Take the first 10 items of newLeads and save it as leadsThisRun.
ListsTake newLeads from item 11 on and save it as leadsForNextRun.Take newLeads from item 11 on and save it as leadsForNextRun.
ListsKeep each item in loadedLedger.rows where item["Routing Rule"] in lowercase is round robin and save it as earlierRoundRobinLeads.Keep each item in loadedLedger.rows where item["Routing Rule"] in lowercase is round robin and save it as earlierRoundRobinLeads.
ListsCount the items in earlierRoundRobinLeads and save it as roundRobinTurn.Count the items in earlierRoundRobinLeads and save it as roundRobinTurn.
ValuesSet leadProblems to an empty list.Set leadProblems to an empty list.
ValuesSet routedThisRun to 0.Set routedThisRun to 0.
ValuesSet droppedThisRun to 0.Set droppedThisRun to 0.
Decisions & LoopsFor each lead in leadsThisRun:For each lead in leadsThisRun:
Decisions & LoopsIf a step below fails, save the error as leadErrorIf a step below fails, save the error as leadError
Try
TextTrim lead["Submission ID"] and save it as submissionId.Trim lead["Submission ID"] and save it as submissionId.
Decisions & LoopsIf submissionId is emptyIf submissionId is empty
Yes
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
TextMake lead.Email lowercase and save it as leadEmail.Make lead.Email lowercase and save it as leadEmail.
Decisions & LoopsIf leadEmail doesn't contain @If leadEmail doesn't contain @
Yes
ValuesShow in the output: Skipped submission submissionId: no usable email address.Show in the output: Skipped submission submissionId: no usable email address.
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
ListsGet the first item of leadEmail split by @ and save it as emailLocalPart.Get the first item of leadEmail split by @ and save it as emailLocalPart.
ListsGet the last item of leadEmail split by @ and save it as emailDomain.Get the last item of leadEmail split by @ and save it as emailDomain.
TextTrim lead.Company and save it as statedCompany.Trim lead.Company and save it as statedCompany.
TextTrim lead.Name and save it as leadName.Trim lead.Name and save it as leadName.
TextTrim lead.Message and save it as leadMessage.Trim lead.Message and save it as leadMessage.
TextTrim lead.Form and save it as formName.Trim lead.Form and save it as formName.
TextMake statedCompany with , replaced by with . replaced by with Inc replaced by with Ltd replaced by with LLC replaced by lowercase and save it as companyKey.Make statedCompany with , replaced by with . replaced by with Inc replaced by with Ltd replaced by with LLC replaced by lowercase and save it as companyKey.
TextCheck whether ,freeMailDomains, contains ,emailDomain, and save it as isFreeMailDomain.Check whether ,freeMailDomains, contains ,emailDomain, and save it as isFreeMailDomain.
TextCheck whether ,throwawayDomains, contains ,emailDomain, and save it as isThrowawayDomain.Check whether ,throwawayDomains, contains ,emailDomain, and save it as isThrowawayDomain.
TextCheck whether ,roleAddressPrefixes, contains ,emailLocalPart, and save it as isRoleAddress.Check whether ,roleAddressPrefixes, contains ,emailLocalPart, and save it as isRoleAddress.
ValuesSet emailStatus to unchecked.Set emailStatus to unchecked.
ValuesSet emailTypoSuggestion to blank.Set emailTypoSuggestion to blank.
Decisions & LoopsIf a step below fails, save the error as verifyErrorIf a step below fails, save the error as verifyError
Try
ZeroBounceZeroBounceVerify the email address leadEmail. Save it as emailCheck.Verify the email address leadEmail. Save it as emailCheck.
TextTrim emailCheck.status and save it as emailStatus.Trim emailCheck.status and save it as emailStatus.
TextTrim emailCheck.did_you_mean and save it as emailTypoSuggestion.Trim emailCheck.did_you_mean and save it as emailTypoSuggestion.
On error
ValuesShow in the output: Could not verify leadEmail - continuing without a deliverability check. verifyError.message.Show in the output: Could not verify leadEmail - continuing without a deliverability check. verifyError.message.
ListsKeep each item in loadedAccounts.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain and save it as accountMatches.Keep each item in loadedAccounts.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain and save it as accountMatches.
Decisions & LoopsIf accountMatches is empty and companyKey isn't emptyIf accountMatches is empty and companyKey isn't empty
Yes
ListsKeep each item in loadedAccounts.rows where item["Account Name"] in lowercase is companyKey and save it as accountMatches.Keep each item in loadedAccounts.rows where item["Account Name"] in lowercase is companyKey and save it as accountMatches.
No
No steps
ListsGet the first item of accountMatches and save it as matchedAccount.Get the first item of accountMatches and save it as matchedAccount.
ValuesSet hasAccountMatch to the length of accountMatches is greater than 0.Set hasAccountMatch to the length of accountMatches is greater than 0.
ValuesSet accountOwnerEmail to blank.Set accountOwnerEmail to blank.
ValuesSet accountOwnerSlackId to blank.Set accountOwnerSlackId to blank.
ValuesSet accountIsCustomer to false.Set accountIsCustomer to false.
ValuesSet accountHasOpenDeal to false.Set accountHasOpenDeal to false.
Decisions & LoopsIf hasAccountMatch is yesIf hasAccountMatch is yes
Yes
TextMake matchedAccount["Owner Email"] lowercase and save it as accountOwnerEmail.Make matchedAccount["Owner Email"] lowercase and save it as accountOwnerEmail.
TextTrim matchedAccount["Owner Slack ID"] and save it as accountOwnerSlackId.Trim matchedAccount["Owner Slack ID"] and save it as accountOwnerSlackId.
ValuesChange accountIsCustomer to matchedAccount["Is Customer"] in lowercase is yes.Change accountIsCustomer to matchedAccount["Is Customer"] in lowercase is yes.
ValuesChange accountHasOpenDeal to matchedAccount["Open Opportunity"] in lowercase is yes.Change accountHasOpenDeal to matchedAccount["Open Opportunity"] in lowercase is yes.
No
No steps
ListsKeep each item in loadedLedger.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain andโ€ฆ and save it as sameDomainRecently.Keep each item in loadedLedger.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain andโ€ฆ and save it as sameDomainRecently.
ValuesSet isBuyingGroup to the length of sameDomainRecently is greater than 0.Set isBuyingGroup to the length of sameDomainRecently is greater than 0.
ValuesSet enrichedTitle to blank.Set enrichedTitle to blank.
ValuesSet enrichedCompany to statedCompany.Set enrichedCompany to statedCompany.
ValuesSet enrichedEmployees to blank.Set enrichedEmployees to blank.
ValuesSet enrichedIndustry to blank.Set enrichedIndustry to blank.
Decisions & LoopsIf a step below fails, save the error as enrichErrorIf a step below fails, save the error as enrichError
Try
ApolloApolloEnrich person leadEmail. Save it as personEnrichment.Enrich person leadEmail. Save it as personEnrichment.
TextTrim personEnrichment.person.title and save it as enrichedTitle.Trim personEnrichment.person.title and save it as enrichedTitle.
On error
ValuesShow in the output: Could not look up the person behind leadEmail - judging on the form alone. enrichError.message.Show in the output: Could not look up the person behind leadEmail - judging on the form alone. enrichError.message.
Decisions & LoopsIf isFreeMailDomain is noIf isFreeMailDomain is no
Yes
Decisions & LoopsIf a step below fails, save the error as orgErrorIf a step below fails, save the error as orgError
Try
ApolloApolloEnrich organization emailDomain. Save it as companyEnrichment.Enrich organization emailDomain. Save it as companyEnrichment.
ValuesSet org to companyEnrichment.organization.Set org to companyEnrichment.organization.
TextTrim org.name and save it as enrichedCompany.Trim org.name and save it as enrichedCompany.
TextTrim org.estimated_num_employees and save it as enrichedEmployees.Trim org.estimated_num_employees and save it as enrichedEmployees.
TextTrim org.industry and save it as enrichedIndustry.Trim org.industry and save it as enrichedIndustry.
On error
ValuesShow in the output: Could not look up the company at emailDomain. orgError.message.Show in the output: Could not look up the company at emailDomain. orgError.message.
No
No steps
Decisions & LoopsIf enrichedTitle is nullIf enrichedTitle is null
Yes
ValuesChange enrichedTitle to blank.Change enrichedTitle to blank.
No
No steps
Decisions & LoopsIf enrichedEmployees is nullIf enrichedEmployees is null
Yes
ValuesChange enrichedEmployees to blank.Change enrichedEmployees to blank.
No
No steps
Decisions & LoopsIf enrichedIndustry is nullIf enrichedIndustry is null
Yes
ValuesChange enrichedIndustry to blank.Change enrichedIndustry to blank.
No
No steps
Decisions & LoopsIf emailStatus is nullIf emailStatus is null
Yes
ValuesChange emailStatus to blank.Change emailStatus to blank.
No
No steps
Decisions & LoopsIf emailTypoSuggestion is nullIf emailTypoSuggestion is null
Yes
ValuesChange emailTypoSuggestion to blank.Change emailTypoSuggestion to blank.
No
No steps
Decisions & LoopsIf enrichedCompany is null or enrichedCompany is emptyIf enrichedCompany is null or enrichedCompany is empty
Yes
ValuesChange enrichedCompany to statedCompany.Change enrichedCompany to statedCompany.
No
No steps
ValuesSet icpFitScore to not scored.Set icpFitScore to not scored.
ValuesSet icpFitReason to blank.Set icpFitReason to blank.
Decisions & LoopsIf a step below fails, save the error as icpErrorIf a step below fails, save the error as icpError
Try
AI AgentRun an AI agent: Score how well this company fits our ideal customer profile. Company: enrichedCompany Weโ€ฆ and save it as icpCheck.Run an AI agent: Score how well this company fits our ideal customer profile. Company: enrichedCompany Weโ€ฆ and save it as icpCheck.
ValuesChange icpFitScore to icpCheck.output.score.Change icpFitScore to icpCheck.output.score.
TextTrim icpCheck.output.reason and save it as icpFitReason.Trim icpCheck.output.reason and save it as icpFitReason.
On error
ValuesShow in the output: The company fit check did not run. icpError.message.Show in the output: The company fit check did not run. icpError.message.
TextCheck whether ,formNamesThatMeanTalkToSalesNow, in lowercase contains ,formName, in lowercase and save it as isHighIntentForm.Check whether ,formNamesThatMeanTalkToSalesNow, in lowercase contains ,formName, in lowercase and save it as isHighIntentForm.
ValuesSet leadDossier to WHO WE SELL TO:Set leadDossier to WHO WE SELL TO: whoYouSellTo WHO WE DO NOT SELL TO: whoYouDoNotSellTo --- THE ENQUIRY --- Form: formName plus High-intent form: isHighIntentForm plus Name: leadName Email: leadEmail Email domain: emailDomain plus Free-mail address: isFreeMailDomain Throwaway address: isThrowawayDomain Role address (info@, sales@): isRoleAddress plus Deliverability: emailStatus Company as typed: statedCompany Company enriched: enrichedCompany Employees: enrichedEmployees Industry: enrichedIndustry Title: enrichedTitle ICP fit score (0-100, from a separate check): icpFitScore Already a known account: hasAccountMatch plus Already a customer: accountIsCustomer Has an open deal: accountHasOpenDeal Others from this company enquired recently: isBuyingGroup plus WHAT THEY WROTE: leadMessage.
ValuesSet triagePrompt to You are triaging one inbound sales enquiry for the sales team described below. Two jobs: decide what this is, and draft the reply.Set triagePrompt to You are triaging one inbound sales enquiry for the sales team described below. Two jobs: decide what this is, and draft the reply. Judge FIT from the company against WHO WE SELL TO and WHO WE DO NOT SELL TO. Judge INTENT from what the person actually wrote and which form they used. They are different axes: a perfect-fit company idly downloading an ebook is not the same as a poor-fit company demanding a call today, and the two need opposite treatment. Read the message before anything else. It is the only place that reveals someone is an agency pitching us, a candidate who couldn't find the careers page, a student doing research, or an existing customer who wanted support. Firmographics cannot catch any of those, and all four score well on paper. Reply in EXACTLY this shape. Every line before the reply delimiter is 'KEY: value' on one line. Do not add commentary, headings or blank lines before the delimiter. INTENT_CLASS: one of buyer, vendor_pitch, job_seeker, student, existing_customer_support, partner_enquiry, competitor, spam, unclear FIT_TIER: A, B, C or D. A is squarely in the profile, D is nowhere near. INTENT_TIER: high, medium or low CONFIDENCE: a number from 0 to 1 EVIDENCE: one short quote from their message that drove the call. If they wrote nothing usable, put NONE. REASONING: one sentence a rep can read in three seconds TEAM_SIZE: a number, or UNKNOWN TIMELINE: what they said about timing, or UNKNOWN CURRENT_TOOLING: tools they mentioned, or UNKNOWN COMPETITOR: a competitor they mentioned switching from, or NONE ---REPLY--- Then the reply itself, written as the rep who will run the call. Open by referencing the specific thing they asked about, in their words, not yours. Say one useful thing. Offer the booking link. Under 90 words, no bullet points, no 'I hope this email finds you well'. If INTENT_CLASS is not buyer, write a short courteous decline or redirect instead - never a sales pitch. If the enquiry genuinely does not say enough to judge, set INTENT_CLASS to unclear and CONFIDENCE below 0.4 rather than guessing. A person will read those. Booking link to offer: bookingLink leadDossier.
ClaudeClaudeAsk Claude: triagePrompt. Save it as triageResponse.Ask Claude: triagePrompt. Save it as triageResponse. Maximum response length: 1400
ValuesSet triage to {parsed:false,intent_class:unclear,fit_tier:D,intent_tier:low,confidence:0,evidence:,reasoning:"T.Set triage to {parsed:false,intent_class:unclear,fit_tier:D,intent_tier:low,confidence:0,evidence:,reasoning:"T.
Decisions & LoopsIf a step below fails, save the error as parseErrorIf a step below fails, save the error as parseError
Try
CodeRun Python code on raw and save it as triage.Run Python code on raw and save it as triage.
On error
ValuesShow in the output: Could not read the triage result for leadEmail - routing it to a human instead. parseError.message.Show in the output: Could not read the triage result for leadEmail - routing it to a human instead. parseError.message.
ValuesSet intentClass to triage.intent_class.Set intentClass to triage.intent_class.
ValuesSet fitTier to triage.fit_tier.Set fitTier to triage.fit_tier.
ValuesSet intentTier to triage.intent_tier.Set intentTier to triage.intent_tier.
ValuesSet decision to route.Set decision to route.
ValuesSet reasonCode to blank.Set reasonCode to blank.
ValuesSet needsHumanEye to false.Set needsHumanEye to false.
Decisions & LoopsIf intentClass is spamIf intentClass is spam
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to INVALID_OR_SPAM.Change reasonCode to INVALID_OR_SPAM.
No
No steps
Decisions & LoopsIf intentClass is vendor_pitchIf intentClass is vendor_pitch
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to VENDOR_PITCH.Change reasonCode to VENDOR_PITCH.
No
No steps
Decisions & LoopsIf intentClass is job_seekerIf intentClass is job_seeker
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to JOB_SEEKER.Change reasonCode to JOB_SEEKER.
No
No steps
Decisions & LoopsIf intentClass is studentIf intentClass is student
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to STUDENT_OR_RESEARCH.Change reasonCode to STUDENT_OR_RESEARCH.
No
No steps
Decisions & LoopsIf intentClass is competitorIf intentClass is competitor
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to COMPETITOR.Change reasonCode to COMPETITOR.
No
No steps
Decisions & LoopsIf intentClass is partner_enquiryIf intentClass is partner_enquiry
Yes
ValuesChange decision to handoff.Change decision to handoff.
ValuesChange reasonCode to PARTNER_ENQUIRY.Change reasonCode to PARTNER_ENQUIRY.
No
No steps
Decisions & LoopsIf intentClass is existing_customer_supportIf intentClass is existing_customer_support
Yes
ValuesChange decision to handoff.Change decision to handoff.
ValuesChange reasonCode to EXISTING_CUSTOMER.Change reasonCode to EXISTING_CUSTOMER.
No
No steps
Decisions & LoopsIf triage.parsed is no or triage.confidence is less than 0.4If triage.parsed is no or triage.confidence is less than 0.4
Yes
ValuesChange needsHumanEye to true.Change needsHumanEye to true.
ValuesChange decision to route.Change decision to route.
ValuesChange reasonCode to LOW_CONFIDENCE.Change reasonCode to LOW_CONFIDENCE.
No
No steps
Decisions & LoopsIf isThrowawayDomain is yesIf isThrowawayDomain is yes
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to INVALID_OR_SPAM.Change reasonCode to INVALID_OR_SPAM.
No
No steps
Decisions & LoopsIf ,invalid,spamtrap,abuse,do_not_mail, contains ,emailStatus,If ,invalid,spamtrap,abuse,do_not_mail, contains ,emailStatus,
Yes
ValuesChange decision to drop.Change decision to drop.
ValuesChange reasonCode to INVALID_OR_SPAM.Change reasonCode to INVALID_OR_SPAM.
No
No steps
Decisions & LoopsIf decision is routeIf decision is route
Yes
Decisions & LoopsIf reasonCode is blank and fitTier is A or fitTier is BIf reasonCode is blank and fitTier is A or fitTier is B
Yes
Decisions & LoopsIf intentTier is lowIf intentTier is low
Yes
ValuesChange decision to nurture.Change decision to nurture.
ValuesChange reasonCode to GOOD_FIT_NOT_NOW.Change reasonCode to GOOD_FIT_NOT_NOW.
No
ValuesChange reasonCode to PURSUE.Change reasonCode to PURSUE.
Else if @reasonCode is blank
Decisions & LoopsIf intentTier is highIf intentTier is high
Yes
ValuesChange decision to handoff.Change decision to handoff.
ValuesChange reasonCode to LOW_FIT_HIGH_INTENT.Change reasonCode to LOW_FIT_HIGH_INTENT.
No
ValuesChange decision to nurture.Change decision to nurture.
ValuesChange reasonCode to LOW_FIT.Change reasonCode to LOW_FIT.
Otherwise
No steps
No
No steps
ValuesSet routedToName to blank.Set routedToName to blank.
ValuesSet routedToEmail to blank.Set routedToEmail to blank.
ValuesSet routedToSlackId to blank.Set routedToSlackId to blank.
ValuesSet routingRule to blank.Set routingRule to blank.
Decisions & LoopsIf decision is not dropIf decision is not drop
Yes
Decisions & LoopsIf accountHasOpenDeal is yes and accountOwnerEmail isn't emptyIf accountHasOpenDeal is yes and accountOwnerEmail isn't empty
Yes
ValuesChange routedToEmail to accountOwnerEmail.Change routedToEmail to accountOwnerEmail.
ValuesChange routedToSlackId to accountOwnerSlackId.Change routedToSlackId to accountOwnerSlackId.
ValuesChange routingRule to open-opportunity owner.Change routingRule to open-opportunity owner.
Else if @hasAccountMatch is yes and @accountOwnerEmail isn'โ€ฆ
ValuesChange routedToEmail to accountOwnerEmail.Change routedToEmail to accountOwnerEmail.
ValuesChange routedToSlackId to accountOwnerSlackId.Change routedToSlackId to accountOwnerSlackId.
ValuesChange routingRule to existing account owner.Change routingRule to existing account owner.
Otherwise
No steps
Decisions & LoopsIf routedToEmail is emptyIf routedToEmail is empty
Yes
ListsKeep each item in loadedReps.rows where item.Available in lowercase is not no and item.Email isn't blank and save it as availableReps.Keep each item in loadedReps.rows where item.Available in lowercase is not no and item.Email isn't blank and save it as availableReps.
Decisions & LoopsIf availableReps is emptyIf availableReps is empty
Yes
ValuesChange routingRule to no rep available.Change routingRule to no rep available.
ValuesChange reasonCode to OWNER_UNAVAILABLE.Change reasonCode to OWNER_UNAVAILABLE.
ValuesChange needsHumanEye to true.Change needsHumanEye to true.
No
MathSet rotationIndex to the remainder of roundRobinTurn divided by the length of availableReps.Set rotationIndex to the remainder of roundRobinTurn divided by the length of availableReps.
ListsSet chosenRep to availableReps[@rotationIndex].Set chosenRep to availableReps[@rotationIndex].
TextTrim chosenRep.Name and save it as routedToName.Trim chosenRep.Name and save it as routedToName.
TextMake chosenRep.Email lowercase and save it as routedToEmail.Make chosenRep.Email lowercase and save it as routedToEmail.
TextTrim chosenRep["Slack ID"] and save it as routedToSlackId.Trim chosenRep["Slack ID"] and save it as routedToSlackId.
ValuesChange routingRule to round robin.Change routingRule to round robin.
ValuesAdd 1 to roundRobinTurn.Add 1 to roundRobinTurn.
No
No steps
No
No steps
ValuesSet crmContactId to blank.Set crmContactId to blank.
Decisions & LoopsIf decision is routeIf decision is route
Yes
Decisions & LoopsIf a step below fails, save the error as crmLookupErrorIf a step below fails, save the error as crmLookupError
Try
HubSpotHubSpotFind the contact leadEmail. Save it as crmLookup.Find the contact leadEmail. Save it as crmLookup.
TextTrim crmLookup.id and save it as crmContactId.Trim crmLookup.id and save it as crmContactId.
On error
Decisions & LoopsIf a step below fails, save the error as crmCreateErrorIf a step below fails, save the error as crmCreateError
Try
HubSpotHubSpotCreate the contact leadEmail. Save it as crmCreated.Create the contact leadEmail. Save it as crmCreated.
TextTrim crmCreated.id and save it as crmContactId.Trim crmCreated.id and save it as crmContactId.
On error
ListsAdd leadEmail was posted and recorded but could not be added to HubSpot, so add them by hand (crmCreateError.message). to the end of leadProblems and save it as leadProblems.Add leadEmail was posted and recorded but could not be added to HubSpot, so add them by hand (crmCreateError.message). to the end of leadProblems and save it as leadProblems.
No
No steps
TextLook up decision in a table and save it as decisionLabel.Look up decision in a table and save it as decisionLabel.
TextLook up fitTier in a table and save it as fitLabel.Look up fitTier in a table and save it as fitLabel.
TextLook up intentTier in a table and save it as intentLabel.Look up intentTier in a table and save it as intentLabel.
TextBuild the text *@decisionLabel* - @fitLabel, @intentLabel and save it as alertHeadline.Build the text *@decisionLabel* - @fitLabel, @intentLabel and save it as alertHeadline.
ValuesSet whoLine to leadName.Set whoLine to leadName.
Decisions & LoopsIf enrichedTitle isn't emptyIf enrichedTitle isn't empty
Yes
ValuesChange whoLine to whoLine, enrichedTitle.Change whoLine to whoLine, enrichedTitle.
No
No steps
Decisions & LoopsIf enrichedCompany isn't emptyIf enrichedCompany isn't empty
Yes
ValuesChange whoLine to whoLine at enrichedCompany.Change whoLine to whoLine at enrichedCompany.
No
No steps
ValuesSet ownerMention to routedToEmail.Set ownerMention to routedToEmail.
Decisions & LoopsIf routedToSlackId isn't emptyIf routedToSlackId isn't empty
Yes
TextBuild the text <@@routedToSlackId> and save it as ownerMention.Build the text <@@routedToSlackId> and save it as ownerMention.
No
No steps
Decisions & LoopsIf routedToEmail is emptyIf routedToEmail is empty
Yes
ValuesChange ownerMention to nobody yet.Change ownerMention to nobody yet.
No
No steps
ValuesSet alertBody to alertHeadlineSet alertBody to alertHeadline whoLine <mailto:leadEmail|leadEmail> ยท form: formName > triage.evidence triage.reasoning Routed to: ownerMention (routingRule).
Decisions & LoopsIf isBuyingGroup is yesIf isBuyingGroup is yes
Yes
ValuesChange alertBody to alertBodyChange alertBody to alertBody :busts_in_silhouette: Someone else from emailDomain also enquired recently - treat this as one buying group.
No
No steps
Decisions & LoopsIf needsHumanEye is yesIf needsHumanEye is yes
Yes
TextLook up reasonCode in a table and save it as humanEyeReason.Look up reasonCode in a table and save it as humanEyeReason.
TextBuild the text @alertBody :eyes: Read this one yourself before replying - @humanEyeReason and save it as alertBody.Build the text @alertBody :eyes: Read this one yourself before replying - @humanEyeReason and save it as alertBody.
No
No steps
Decisions & LoopsIf emailTypoSuggestion isn't emptyIf emailTypoSuggestion isn't empty
Yes
ValuesChange alertBody to alertBodyChange alertBody to alertBody :warning: Possible typo in the address - did they mean emailTypoSuggestion?.
No
No steps
Decisions & LoopsIf decision is not dropIf decision is not drop
Yes
ValuesChange alertBody to alertBodyChange alertBody to alertBody *Suggested reply* triage.reply.
Decisions & LoopsIf a step below fails, save the error as slackErrorIf a step below fails, save the error as slackError
Try
SlackSlackSend a message to slackChannelId.Send a message to slackChannelId.alertBody
On error
Decisions & LoopsStop and report a problem: Could not post to Slack, so nobody would hear about this lead. Check the channel id on the step called 'Create slackChannelId', and make sure the Lodol app has been invited to that channel with /invite Lodol. The underlying error was: slackError.message.Stop and report a problem: Could not post to Slack, so nobody would hear about this lead. Check the channel id on the step called 'Create slackChannelId', and make sure the Lodol app has been invited to that channel with /invite Lodol. The underlying error was: slackError.message.
ValuesAdd 1 to routedThisRun.Add 1 to routedThisRun.
No
ValuesAdd 1 to droppedThisRun.Add 1 to droppedThisRun.
Decisions & LoopsIf replyMode in lowercase is draft and decision is routeIf replyMode in lowercase is draft and decision is route
Yes
Decisions & LoopsIf a step below fails, save the error as draftErrorIf a step below fails, save the error as draftError
Try
GmailGmailDraft an email to leadEmail.Draft an email to leadEmail. Subject: Re: formNametriage.reply
On error
ListsAdd leadEmail was posted to Slack and recorded, but the Gmail draft could not be saved, so reply from the suggested text in Slack (draftError.message). to the end of leadProblems and save it as leadProblems.Add leadEmail was posted to Slack and recorded, but the Gmail draft could not be saved, so reply from the suggested text in Slack (draftError.message). to the end of leadProblems and save it as leadProblems.
No
No steps
Dates & TimesMove the current date and time by replyWithinMinutes minutes and save it as replyDueAt.Move the current date and time by replyWithinMinutes minutes and save it as replyDueAt.
Decisions & LoopsIf a step below fails, save the error as ledgerErrorIf a step below fails, save the error as ledgerError
Try
Google SheetsGoogle SheetsAdd a row to 'Ledger' in spreadsheetUrl.Add a row to 'Ledger' in spreadsheetUrl.
On error
Decisions & LoopsStop and report a problem: Stopped: leadEmail (submission submissionId) was handled but could not be added to the 'Ledger' tab. The next run will handle it again, so if it was posted to Slack it will be posted a second time. Check that the Google Sheets connection can edit the spreadsheet and that the 'Ledger' tab is still there. The error was: ledgerError.message.Stop and report a problem: Stopped: leadEmail (submission submissionId) was handled but could not be added to the 'Ledger' tab. The next run will handle it again, so if it was posted to Slack it will be posted a second time. Check that the Google Sheets connection can edit the spreadsheet and that the 'Ledger' tab is still there. The error was: ledgerError.message.
On error
ListsAdd lead.Email (submission lead["Submission ID"]) could not be triaged and was not recorded, so the next run tries it again (leadError.message). to the end of leadProblems and save it as leadProblems.Add lead.Email (submission lead["Submission ID"]) could not be triaged and was not recorded, so the next run tries it again (leadError.message). to the end of leadProblems and save it as leadProblems.
MathSet handledThisRun to routedThisRun plus droppedThisRun.Set handledThisRun to routedThisRun plus droppedThisRun.
ListsCount the items in leadsForNextRun and save it as waitingCount.Count the items in leadsForNextRun and save it as waitingCount.
Decisions & LoopsIf leadProblems isn't emptyIf leadProblems isn't empty
Yes
TextJoin leadProblems with a new line and save it as problemList.Join leadProblems with a new line and save it as problemList.
Decisions & LoopsStop and report a problem: New leads handled: handledThisRun. Some need attention:Stop and report a problem: New leads handled: handledThisRun. Some need attention: problemList.
No
No steps
Decisions & LoopsIf waitingCount is greater than 0If waitingCount is greater than 0
Yes
Decisions & LoopsFinish the run: New leads handled: handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped). Still waiting: waitingCount - they are picked up by the next runs, 10 at a time.Finish the run: New leads handled: handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped). Still waiting: waitingCount - they are picked up by the next runs, 10 at a time.
No
No steps
Decisions & LoopsIf handledThisRun is 0If handledThisRun is 0
Yes
Decisions & LoopsFinish the run: No new leads on the 'New leads' tab.Finish the run: No new leads on the 'New leads' tab.
No
No steps
Decisions & LoopsFinish the run: New leads handled: handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped).Finish the run: New leads handled: handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped).