Daily SEO keyword rank tracker with Slack drop alerts
Every weekday morning, check where your keywords rank on Google, log them to a sheet, and get a Slack ping the moment anything slips out of the top 10.
Build me a daily SEO keyword rank tracker as a code workflow. Keep it deterministic with no LLM step.
Trigger: cron schedule, every weekday at 7am in my local timezone.
Inputs: a Google Sheets spreadsheet that has a tab called 'keywords' with columns keyword, target_domain, country. Use Google Sheets Get Values to read all rows on that tab.
For each row, call Bright Data's SERP Search operation against Google in the row's country locale. Parse the organic results and find the highest-ranking URL whose host matches the target_domain (including subdomains). Capture the rank position (1 to 100), the landing URL, and the total number of organic results scanned.
Append the result to a 'rank_history' tab on the same spreadsheet using Google Sheets Append Values. Columns: date (today's date in YYYY-MM-DD), keyword, rank (an integer 1 to 100, or the literal string 'not in top 100' if the domain wasn't found), landing_url (empty if not found), total_results_scanned.
After every keyword has been written, read yesterday's snapshot from the same rank_history tab (filter rows where date equals yesterday). For each keyword, diff yesterday's rank against today's. Flag a keyword as a regression if either: the numeric rank dropped by 3 or more positions, OR it was in the top 10 yesterday (rank 1 to 10) and is now rank 11+ or 'not in top 100'.
If at least one keyword regressed, send a single batched Slack message via Send a Message to a Slack channel the user will configure (e.g. #seo). The message should have a short header like 'SEO rank drops for {date}' and then one line per regression with: keyword, old rank, new rank, landing URL. Use Slack mrkdwn formatting (single asterisks for bold). If no keywords regressed, skip the Slack step entirely.
Integrations: Bright Data (SERP Search), Google Sheets (Get Values, Append Values), Slack (Send a Message). The value is a clean rank history log plus a same-day alert when something slips, so the SEO team can react before competitors widen the gap.
Additional information
What does this prompt do?
- Checks where each of your tracked keywords ranks on Google every weekday at 7am.
- Logs the date, position, and landing page for every keyword to a Google Sheet you can chart over time.
- Compares today's results to yesterday's and flags any keyword that lost real ground.
- Posts a single batched Slack message to your SEO channel listing only the keywords that slipped, so the team can react before competitors widen the gap.
What do I need to use this?
- A Bright Data account with access to their search results product.
- A Google Sheet with a 'keywords' tab listing the keyword, target domain, and country for each row.
- A Google account that can read and write that spreadsheet.
- A Slack workspace and the channel you want regression alerts posted to.
How can I customize it?
- Change the schedule to run twice a day, only on Mondays, or right before your weekly SEO standup.
- Adjust what counts as a meaningful drop. The default is a fall of 3 or more positions, or falling out of the top 10.
- Swap the destination channel for a private SEO room, a client-specific channel, or a direct message to the lead.
- Add competitor domains as extra rows for the same keyword to track them side by side.
- Mix countries in the same sheet. The 'country' column controls the Google locale for each row, so US, UK, DE, and FR keywords can all live together.
Frequently asked questions
Do I need an LLM or AI step for this to work?
How many keywords can I track?
What happens if my domain is not in the top 100?
Can I track competitor rankings at the same time?
Can I run this for countries other than the US?
Why send alerts to Slack instead of email?
Stop refreshing the SERP every morning.
Connect Bright Data, Google Sheets, and Slack once, and Geni runs your rank check every weekday at 7am and pings you the second anything slips.