{
  "name": "07 App Store + Google Play negative review alerts",
  "nodes": [
    {
      "parameters": {
        "content": "## Negative review alerts\nEvery 12h checks the newest App Store and Google Play reviews and alerts you about 1-2 star reviews so you can respond fast.\n\n1. Open **Config** and paste your Apify API token (free account: console.apify.com -> Settings -> API & Integrations).\n2. Paste a Discord/Slack webhook URL and/or a Telegram bot token + chat ID (delete the node you don't use).\n3. Click **Test workflow**, then switch it to **Active**.",
        "height": 340,
        "width": 420
      },
      "name": "How to use",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -400
      ],
      "id": "1e3fcb47-16ec-462c-b973-762b33c1328a"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 12
            }
          ]
        }
      },
      "name": "Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "id": "1bb1bc27-4bed-49e8-8899-e67ab92f9de7"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "6dffe257-8774-40e2-8ab6-545a8ffb69e3",
              "name": "apifyToken",
              "value": "YOUR_APIFY_TOKEN",
              "type": "string"
            },
            {
              "id": "60551333-03a3-4d76-b9ab-2fbf8f6b24cc",
              "name": "webhookUrl",
              "value": "https://discord.com/api/webhooks/...",
              "type": "string"
            },
            {
              "id": "b12fa0e7-4471-4281-a3bd-e3e61f3b545a",
              "name": "telegramBotToken",
              "value": "",
              "type": "string"
            },
            {
              "id": "d059bbeb-419b-445d-8d1a-604b71ab2376",
              "name": "telegramChatId",
              "value": "",
              "type": "string"
            },
            {
              "id": "3e8a30fc-3c9b-402c-b191-6e6fbd93eb54",
              "name": "appStoreUrl",
              "value": "https://apps.apple.com/us/app/notion/id1232780281",
              "type": "string"
            },
            {
              "id": "98fbb1a1-c300-4b7f-a81c-b1b7475ec97d",
              "name": "playStoreUrl",
              "value": "https://play.google.com/store/apps/details?id=notion.id",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ],
      "id": "5e2cbecd-e634-4b49-a627-27945aade15f"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.apify.com/v2/acts/martin10291~app-reviews-scraper/run-sync-get-dataset-items",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "token",
              "value": "={{ $('Config').item.json.apifyToken }}"
            },
            {
              "name": "timeout",
              "value": "280"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({apps: [$('Config').item.json.appStoreUrl, $('Config').item.json.playStoreUrl].filter(Boolean), maxReviewsPerApp: 50, sortBy: 'newest', ratings: [1, 2]}) }}",
        "options": {
          "timeout": 300000
        }
      },
      "name": "Run Apify scraper",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        0
      ],
      "id": "052a9fbb-c6ca-4a61-934e-cd8393a4372e"
    },
    {
      "parameters": {
        "jsCode": "const rows = $input.all();\nif (!rows.length) return [];\nconst cut = Date.now() - 12*3600*1000;\nconst d = rows.map(i => i.json).filter(r => (r.rating || r.score || 5) <= 2 && (!r.date || new Date(r.date).getTime() > cut));\nif (!d.length) return [];\nconst text = 'New 1-2★ reviews:\\n' + d.slice(0, 10).map(r => `★${r.rating} ${r.appName || ''} – ${r.title || ''}: ${(r.text || r.review || '').slice(0, 200)}`).join('\\n\\n');\nreturn [{ json: { text } }];"
      },
      "name": "Format message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ],
      "id": "9958ee10-74c6-4c03-a253-c25e53ed57c9"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $('Config').item.json.webhookUrl }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({content: $json.text, text: $json.text}) }}",
        "options": {}
      },
      "name": "Send to Discord or Slack",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        0
      ],
      "id": "7a679649-f3e0-4a90-a790-87d90c16d079"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegramBotToken }}/sendMessage",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({chat_id: $('Config').item.json.telegramChatId, text: $json.text, disable_web_page_preview: true}) }}",
        "options": {}
      },
      "name": "Send to Telegram",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        200
      ],
      "id": "b1ecf5e2-02ba-453a-9938-7631ecf7233e"
    }
  ],
  "connections": {
    "Schedule": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Run Apify scraper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Apify scraper": {
      "main": [
        [
          {
            "node": "Format message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format message": {
      "main": [
        [
          {
            "node": "Send to Discord or Slack",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "active": false
}