> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiveku.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Recipe: Alert on SEO Ranking Drops

> Get a notification when one of your tracked keywords drops in search rankings

Catch SEO regressions (Google core update, content change, broken page) the morning they happen — before they tank a month of traffic.

<Info>
  Before you start: connect [Google Search Console](/how-tos/connect-gsc) and have at least a few keywords being tracked. You'll also need a Slack webhook or email address for the alert destination.
</Info>

## Two Paths

<Tabs>
  <Tab title="Built-in SEO alerts (Simplest)">
    If you just want "ping me when a keyword drops," use the built-in alerts — no workflow required.

    **Marketing > SEO > Settings > Rank Alerts**

    Toggle on, pick a threshold (default 5 positions), pick a destination (email, Slack), save. Done.

    This covers 80% of what most teams need. Use the custom workflow below when you want bespoke logic — filtering by keyword tier, different thresholds per category, or routing to different channels.
  </Tab>

  <Tab title="Custom workflow (Flexible)">
    Build it as a workflow when you need custom logic. Keep reading.
  </Tab>
</Tabs>

## The Flow at a Glance

<CardGroup cols={3}>
  <Card title="1. Daily schedule" icon="clock">
    Runs every morning
  </Card>

  <Card title="2. Fetch rankings" icon="chart-line">
    Pull today vs yesterday
  </Card>

  <Card title="3. Alert if dropped" icon="triangle-exclamation">
    Threshold-based Slack ping
  </Card>
</CardGroup>

## Step 1: Build the Workflow

<Steps>
  <Step title="Start a new workflow">
    **Workflows** > **New Workflow**. Name it `Daily SEO Rank Check`.
  </Step>

  <Step title="Add a Schedule trigger">
    Click **Add Trigger** > **Schedule**. Use cron syntax:

    ```
    cron(0 8 * * ? *)
    ```

    That's 8:00 AM UTC daily. Adjust to your preferred time zone by offsetting (e.g., `cron(0 13 * * ? *)` for 8 AM ET in winter).
  </Step>

  <Step title="Add an HTTP Request action to fetch rankings">
    Click **+ Add Action** > **HTTP Request**. Configure to query Hiveku's internal SEO endpoint:

    * **Method:** GET
    * **URL:** `https://api.hiveku.com/seo/rankings/diff?project_id={{project_id}}&days=1`
    * **Auth:** use the Hiveku API key env var

    The response is a JSON list of `{ keyword, url, yesterday_position, today_position, delta }` objects. Name the output `rankings`.
  </Step>

  <Step title="Add a Conditional">
    Click **+ Add Action** > **Conditional**. Branch on:

    ```
    {{rankings}} has any item where delta <= -5
    ```

    That means: continue only if at least one keyword dropped 5 or more positions since yesterday.
  </Step>

  <Step title="Add a Slack notification">
    In the true branch, add **HTTP Request** pointed at your Slack webhook:

    ```json theme={null}
    {
      "text": "SEO rank drops detected today:\n{{#each rankings.filter(delta <= -5)}}• {{keyword}} — {{yesterday_position}} → {{today_position}} ({{delta}}) — {{url}}\n{{/each}}"
    }
    ```
  </Step>

  <Step title="Save and enable">
    Save, flip enabled. The workflow runs tomorrow at 8 AM UTC by default.
  </Step>
</Steps>

<Tip>
  To test without waiting 24 hours, temporarily change the trigger to `rate(5 minutes)` and mock a ranking drop by editing the tracked keywords table. Remember to change it back after.
</Tip>

## Customizing

### Threshold

5 positions is a reasonable default. GSC data naturally fluctuates ±2 positions day-to-day — below 5 you'll get noisy alerts. Raise to 10 if you only care about catastrophic drops.

### Frequency

* `cron(0 8 * * ? *)` — daily at 8 AM UTC
* `cron(0 */6 * * ? *)` — every 6 hours
* `rate(1 hour)` — hourly, but GSC data only updates every 2–3 days so this is usually overkill

### Scope

To only alert on high-priority keywords, add a filter to the HTTP request:

```
?project_id={{project_id}}&days=1&tier=priority
```

Set the `tier` on keywords in **Marketing > SEO > Keywords**.

### Group by Category

Add an AI Generation step before the Slack action to summarize drops grouped by topic:

```
Summarize these SEO rank drops into a digest.
Group by page topic. Highlight the most critical one first.
Data: {{rankings}}
```

## Test It

<Steps>
  <Step title="Mock a drop">
    In **Marketing > SEO > Keywords**, edit one tracked keyword and manually set its `yesterday_position` to 5 and `today_position` to 15. This simulates a 10-position drop.
  </Step>

  <Step title="Trigger the workflow manually">
    On the workflow page, click **Run Now**. The run appears in the **Runs** tab.
  </Step>

  <Step title="Check Slack">
    A rank-drop alert should show up in your target channel.
  </Step>

  <Step title="Restore the keyword">
    Reset the keyword values you mocked, otherwise the next real run will still think they dropped.
  </Step>
</Steps>

## Troubleshooting

<AccordionGroup>
  <Accordion title="No alerts firing — but I know rankings changed">
    Two common causes: (1) threshold is too high — lower it and re-test; (2) GSC hasn't synced today's data yet. GSC updates on a 2–3 day lag and the API reflects whatever's available. Check **Marketing > SEO > Keywords** — if the "last updated" timestamp is more than 2 days old, the issue is on the Search Console side.
  </Accordion>

  <Accordion title="False positives — keywords 'drop' then recover next day">
    Normal GSC fluctuation. Raise the threshold to 5+ positions, or compare a 7-day average instead of day-over-day. In the HTTP request, use `?days=7` and alert only if the 7-day trailing average dropped.
  </Accordion>

  <Accordion title="Alerts too noisy">
    Filter to a priority tier (see Scope above), or group alerts by category so you get one digest message instead of 20 individual ones. You can also throttle: only alert if the same keyword dropped 2 days in a row.
  </Accordion>

  <Accordion title="Workflow doesn't fire at the scheduled time">
    Check the schedule in UTC, not your local time zone. Cron expressions always run on UTC in Hiveku. Also verify the workflow is enabled — scheduled workflows that aren't enabled silently never fire.
  </Accordion>

  <Accordion title="HTTP request returns 401 / 403">
    The Hiveku API call needs an authenticated request. Make sure the HTTP action uses the **Hiveku API Key** connection (or env var `HIVEKU_API_KEY`), not a raw unauthenticated call.
  </Accordion>
</AccordionGroup>

## What's Next?

<CardGroup cols={2}>
  <Card title="Connect Search Console" icon="magnifying-glass" href="/how-tos/connect-gsc">
    Set up the GSC connection that powers rank tracking
  </Card>

  <Card title="SEO Audit" icon="list-check" href="/how-tos/seo-audit">
    Find the pages behind dropping keywords and fix them
  </Card>

  <Card title="Weekly Digest" icon="envelope" href="/how-tos/workflow-weekly-digest">
    Combine rank changes into a weekly team summary
  </Card>
</CardGroup>
