{
  "name": "Alert Slack when Local Falcon rankings drop",
  "nodes": [
    {
      "parameters": {
        "content": "## Alert Slack When Local Falcon Rankings Drop\n\n**Who is this for:** SEO teams and agencies who need immediate notifications when client rankings decline, enabling quick response to ranking issues.\n\n**What this workflow does:**\n1. Runs daily at 8am to check your trend reports\n2. Analyzes ranking changes across all tracked locations\n3. Filters for any locations that dropped in position\n4. Sends a detailed Slack alert only when drops are detected\n5. Skips notification if all rankings are stable or improved\n\n**How to set up:**\n1. Add your Local Falcon API credentials (get your key at https://www.localfalcon.com/api/credentials)\n2. Connect your Slack workspace and select a channel\n3. Configure the alert threshold (minimum drop to trigger alert)\n4. Activate the workflow\n\n**Requirements:**\n- Local Falcon account with API access and existing trend reports\n- Slack workspace with permission to post to channels\n\n**How to customize:**\n- Adjust the schedule frequency (hourly for high-priority clients)\n- Change the drop threshold in the Filter node\n- Add email as a backup notification channel\n- Include specific location or keyword filters",
        "height": 540,
        "width": 440,
        "color": 5
      },
      "id": "sticky-main",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        140,
        -180
      ]
    },
    {
      "parameters": {
        "content": "### Step 1: Schedule\nRuns daily at 8am. Adjust timing based on your needs.",
        "height": 100,
        "width": 200
      },
      "id": "sticky-step1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        80,
        660
      ]
    },
    {
      "parameters": {
        "content": "### Step 2: Settings\nConfigure Slack channel and alert threshold here.",
        "height": 100,
        "width": 200
      },
      "id": "sticky-step2",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        340,
        660
      ]
    },
    {
      "parameters": {
        "content": "### Step 3: Get Trends\nFetches trend reports showing rank changes over time.",
        "height": 100,
        "width": 200
      },
      "id": "sticky-step3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        600,
        660
      ]
    },
    {
      "parameters": {
        "content": "### Step 4: Filter Drops\nIdentifies locations with rank drops above threshold.",
        "height": 100,
        "width": 200
      },
      "id": "sticky-step4",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        860,
        660
      ]
    },
    {
      "parameters": {
        "content": "### Step 5: Alert\nSends formatted alert to Slack with drop details.",
        "height": 100,
        "width": 200
      },
      "id": "sticky-step5",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1120,
        660
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "triggerAtHour": 8
            }
          ]
        }
      },
      "id": "schedule",
      "name": "Every Day 8am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        180,
        440
      ]
    },
    {
      "parameters": {
        "mode": "raw",
        "jsonOutput": "{\n  \"slackChannel\": \"#seo-alerts\",\n  \"dropThreshold\": 1,\n  \"reportLimit\": 50\n}",
        "options": {}
      },
      "id": "settings",
      "name": "Alert Settings",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        440,
        440
      ]
    },
    {
      "parameters": {
        "resource": "report",
        "operation": "listTrend",
        "additionalFields": {
          "limit": "={{ $json.reportLimit }}"
        }
      },
      "id": "get-trends",
      "name": "Get Trend Reports",
      "type": "@local-falcon/n8n-nodes-localfalcon.localFalcon",
      "typeVersion": 1,
      "position": [
        700,
        440
      ],
      "credentials": {
        "localFalconApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Get settings and reports\nconst settings = $('Alert Settings').first().json;\nconst reports = $input.first().json.reports || [];\nconst alerts = [];\n\nfor (const report of reports) {\n  // Check if rank dropped (positive change = worse ranking)\n  const rankChange = parseFloat(report.rank_change) || 0;\n  \n  if (rankChange >= settings.dropThreshold) {\n    alerts.push({\n      location: report.location_name || 'Unknown Location',\n      keyword: report.keyword || 'Unknown Keyword',\n      previousRank: report.previous_avg_rank || 'N/A',\n      currentRank: report.avg_rank || 'N/A',\n      change: rankChange,\n      platform: report.platform || 'google'\n    });\n  }\n}\n\n// Stop workflow if no drops detected\nif (alerts.length === 0) {\n  return [];\n}\n\n// Format message for Slack\nlet message = `:warning: *Local Falcon Rank Drop Alert*\\n\\n`;\nmessage += `*${alerts.length} location(s)* dropped in rankings:\\n\\n`;\n\nfor (const alert of alerts) {\n  message += `\u2022 *${alert.location}* - \"${alert.keyword}\"\\n`;\n  message += `  Platform: ${alert.platform} | Rank: ${alert.previousRank} \u2192 ${alert.currentRank} (dropped ${alert.change} positions)\\n\\n`;\n}\n\nreturn [{\n  json: {\n    alerts,\n    alertCount: alerts.length,\n    slackMessage: message,\n    slackChannel: settings.slackChannel\n  }\n}];"
      },
      "id": "filter-drops",
      "name": "Filter Rank Drops",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        440
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.slackChannel }}"
        },
        "text": "={{ $json.slackMessage }}",
        "otherOptions": {}
      },
      "id": "slack-alert",
      "name": "Send Slack Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1220,
        440
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Every Day 8am": {
      "main": [
        [
          {
            "node": "Alert Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Settings": {
      "main": [
        [
          {
            "node": "Get Trend Reports",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Trend Reports": {
      "main": [
        [
          {
            "node": "Filter Rank Drops",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Rank Drops": {
      "main": [
        [
          {
            "node": "Send Slack Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}