Watches your competitors across news, social and review sites, and posts to Slack only when something changes how you sell against them.
Uses
ClaudeIsItDownStatus
Serper
Slack
Hear in Slack when a competitor does something that matters
Every day, the workflow sweeps where each competitor you name shows up: news from the past day, social sites from the past week and review sites from the past month. If you point it at a competitor's status page it also checks whether they are down. Anything new is put to the AI with one question: does any of this change how you sell against them?
When the answer is yes, a short battlecard note lands in your Slack channel: what happened, why it matters and a line a rep can use on a call. Funding, launches, pricing changes, outages and a pattern of complaints count; when nothing changes the picture, nothing is posted. Links already analysed are remembered, so a thread or a review is read once rather than every morning, and a problem with one competitor is reported without stopping the others.
Before the first run you need a Slack channel, the competitor names and a one-line description of your market, so a same-named company elsewhere is not mistaken for a rival.
competitors to [{name:Acme Analytics,statusSlug:}, {name:Globex Software,statusSlug:}].Set competitors to [{name:Acme Analytics,statusSlug:}, {name:Globex Software,statusSlug:}].yourMarket to B2B analytics software for mid-market finance teams.Set yourMarket to B2B analytics software for mid-market finance teams.slackChannelId to blank.Set slackChannelId to blank.reviewSites to (site:g2.com OR site:capterra.com OR site:trustradius.com OR site:trustpilot.com OR site:getapp.com OR site:softwareadvice.com).Set reviewSites to (site:g2.com OR site:capterra.com OR site:trustradius.com OR site:trustpilot.com OR site:getapp.com OR site:softwareadvice.com).socialSites to (site:reddit.com OR site:news.ycombinator.com OR site:x.com OR site:linkedin.com OR site:youtube.com).Set socialSites to (site:reddit.com OR site:news.ycombinator.com OR site:x.com OR site:linkedin.com OR site:youtube.com).handledStore.Get the stored value 'handled_mentions'. Save it as handledStore.today.Get today's date and save it as today.handled to an empty list.Set handled to an empty list.handledKeys to an empty list.Set handledKeys to an empty list.handledStore.found is yesIf handledStore.found is yesstoreErrorIf a step below fails, save the error as storeErrorentry in handledStore.value:For each entry in handledStore.value:today and entry.expires in days is greater than or… If the difference between today and entry.expires in days is greater than or…entry to the end of handled and save it as handled.Add entry to the end of handled and save it as handled.entry.key to the end of handledKeys and save it as handledKeys.Add entry.key to the end of handledKeys and save it as handledKeys.storeError.message.Show in the output: The stored list of already-analysed mentions could not be read, so this run treats everything it finds as new. storeError.message.handled to an empty list.Change handled to an empty list.handledKeys to an empty list.Change handledKeys to an empty list.competitor in competitors:For each competitor in competitors:sweepErrorIf a step below fails, save the error as sweepErrorcompetitorName to competitor.name.Set competitorName to competitor.name.statusSlug to competitor.statusSlug.Set statusSlug to competitor.statusSlug.competitorName. Save it as news.Search Google News for competitorName. Save it as news.@competitorName socialSites'. Save it as social.Search Google for '@competitorName socialSites'. Save it as social.@competitorName review pricing complaints reviewSites'. Save it as reviews.Search Google for '@competitorName review pricing complaints reviewSites'. Save it as reviews.keyPrefix to competitorName|.Set keyPrefix to competitorName|.news.articles where handledKeys doesn't contain keyPrefix plus item.link and save it as newArticles.Keep each item in news.articles where handledKeys doesn't contain keyPrefix plus item.link and save it as newArticles.social.results where handledKeys doesn't contain keyPrefix plus item.link and save it as newSocial.Keep each item in social.results where handledKeys doesn't contain keyPrefix plus item.link and save it as newSocial.reviews.results where handledKeys doesn't contain keyPrefix plus item.link and save it as newReviews.Keep each item in reviews.results where handledKeys doesn't contain keyPrefix plus item.link and save it as newReviews.statusNote to blank.Set statusNote to blank.serviceDown to false.Set serviceDown to false.statusSlug isn't emptyIf statusSlug isn't emptystatusErrorIf a step below fails, save the error as statusErrorstatusSlug. Save it as serviceStatus.Get status for statusSlug. Save it as serviceStatus.statusNote to Service status right now: serviceStatus.status (serviceStatus.report_count_24h as text problem reports in 24h). serviceStatus.status_page_url.Change statusNote to Service status right now: serviceStatus.status (serviceStatus.report_count_24h as text problem reports in 24h). serviceStatus.status_page_url.serviceDown to serviceStatus.status is not operational.Change serviceDown to serviceStatus.status is not operational.statusError.message.Show in the output: Could not read the service status for '@statusSlug'. Check the slug at isitdownstatus.com, or clear it. statusError.message.newArticles plus the length of newSocial plus the length of…If the length of newArticles plus the length of newSocial plus the length of…competitorName: every mention found today was already analysed on an earlier run, and no outage is showing.Show in the output: Nothing new for competitorName: every mention found today was already analysed on an earlier run, and no outage is showing.findings to COMPETITOR: competitorNameSet findings to COMPETITOR: competitorName
OUR MARKET: yourMarket
--- NEWS (past 24 hours, not seen on an earlier run) ---
newArticles as text
--- SOCIAL (past week, not seen on an earlier run) ---
newSocial as text
--- REVIEW SITES (past month, not seen on an earlier run) ---
newReviews as text
--- SERVICE STATUS ---
statusNote.findings'. Save it as analysis.
Maximum response length: 1500analysis.response_text and save it as verdict.Trim analysis.response_text and save it as verdict.verdict isn't empty and verdict doesn't contain NO_CHANGE (ignoring case)If verdict isn't empty and verdict doesn't contain NO_CHANGE (ignoring case)slackChannelId. Save it as posted.Send a message to slackChannelId. Save it as posted.*Competitor update — competitorName*
verdicttoday and save it as newsExpiry.Get the date 2 days after today and save it as newsExpiry.today and save it as socialExpiry.Get the date 8 days after today and save it as socialExpiry.today and save it as reviewExpiry.Get the date 32 days after today and save it as reviewExpiry.article in newArticles:For each article in newArticles:handled and save it as handled. Add a record of key and expires to the end of handled and save it as handled.post in newSocial:For each post in newSocial:handled and save it as handled. Add a record of key and expires to the end of handled and save it as handled.review in newReviews:For each review in newReviews:handled and save it as handled. Add a record of key and expires to the end of handled and save it as handled.handled is greater than 300If the length of handled is greater than 300handled from position the length of handled minus 300 on and save it as handled.Take handled from position the length of handled minus 300 on and save it as handled.handled.Set the stored value 'handled_mentions' to handled.competitor.name as text: sweepError.message.Show in the output: Competitor sweep failed for competitor.name as text: sweepError.message.