{
  "name": "Mangools: Weekly Rank Report (SERPWatcher via MCP)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "weeksInterval": 1,
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8,
              "triggerAtMinute": 0
            }
          ]
        }
      },
      "id": "9218fa30-e8b3-49a6-89aa-7e8636b33cfa",
      "name": "Every Monday 08:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.4,
      "position": [
        -460,
        -80
      ]
    },
    {
      "parameters": {},
      "id": "fcc536bf-fa70-46d9-bae5-ad6ab86afa5c",
      "name": "When clicking ‘Execute workflow’ (test run)",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -460,
        100
      ]
    },
    {
      "parameters": {
        "content": "## Weekly rank report (SERPWatcher)\nBoth SERPWatcher tools this workflow calls are free and spend no lookups. After import, open the two **MCP Client** nodes and pick your own **Mangools API key** credential (Header Auth, header name `x-access-token`, value: your key from https://mangools.com/api-token).\n\nThe report covers the last 7 complete days (UTC). The Schedule Trigger runs it every Monday at 08:00 in your n8n time zone once the workflow is published; use the Manual Trigger to try it now.",
        "height": 300,
        "width": 400
      },
      "id": "79337cd5-c30b-4d92-afdb-5c3b8eddc27e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -460,
        -420
      ]
    },
    {
      "parameters": {
        "serverTransport": "httpStreamable",
        "endpointUrl": "https://mcp.mangools.com/mcp",
        "authentication": "headerAuth",
        "tool": {
          "__rl": true,
          "value": "serpwatcher_list_trackings",
          "mode": "list",
          "cachedResultName": "serpwatcher_list_trackings"
        },
        "inputMode": "json",
        "jsonInput": "{\n  \"limit\": 1000\n}\n",
        "options": {}
      },
      "id": "8bdffc2a-4f7f-4f95-a477-b533c687c558",
      "name": "List trackings (SERPWatcher)",
      "type": "@n8n/n8n-nodes-langchain.mcpClient",
      "typeVersion": 1.1,
      "position": [
        -220,
        0
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": null,
          "name": "Mangools API key"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "04424308-62b9-41f1-95b1-69faa324a591",
              "leftValue": "={{ $json.content[0].text.trackings.length }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2e948a75-e235-4ff0-87d5-916b9e59fe2d",
      "name": "Has any trackings?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const trackings = $input.first().json.content?.[0]?.text?.trackings ?? [];\n\nreturn trackings.map((t) => ({\n  json: {\n    tracking_id: t.id,\n    domain: t.domain,\n    location: t.location,\n    device: t.platform_id === 2 ? 'mobile' : 'desktop',\n    keywords_count: t.keywords_count,\n  },\n}));"
      },
      "id": "99cedfcd-de76-413c-b93a-08bde41de695",
      "name": "One item per tracking",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        -120
      ]
    },
    {
      "parameters": {
        "serverTransport": "httpStreamable",
        "endpointUrl": "https://mcp.mangools.com/mcp",
        "authentication": "headerAuth",
        "tool": {
          "__rl": true,
          "value": "serpwatcher_get_tracking_stats",
          "mode": "list",
          "cachedResultName": "serpwatcher_get_tracking_stats"
        },
        "inputMode": "json",
        "jsonInput": "={{ { \"tracking_id\": $json.tracking_id, \"from\": $now.toUTC().minus({ days: 8 }).toFormat('yyyy-MM-dd') + 'Z+0000', \"to\": $now.toUTC().minus({ days: 1 }).toFormat('yyyy-MM-dd') + 'Z+0000', \"limit\": Math.max(1, $json.keywords_count) } }}",
        "options": {}
      },
      "id": "d537f552-5061-40ca-b983-9d1ecd225d3a",
      "name": "Get tracking stats (SERPWatcher)",
      "type": "@n8n/n8n-nodes-langchain.mcpClient",
      "typeVersion": 1.1,
      "position": [
        440,
        -120
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": null,
          "name": "Mangools API key"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "let trackingMeta = [];\ntry {\n  trackingMeta = $('One item per tracking').all();\n} catch (e) {\n  trackingMeta = [];\n}\n\nif (trackingMeta.length === 0) {\n  return [{\n    json: {\n      summary_text: 'Mangools weekly rank report\\n\\nNo SERPWatcher trackings found on this account yet. Add a tracking in SERPWatcher to start getting weekly reports.',\n    },\n  }];\n}\n\nconst statsItems = $input.all();\nconst lines = ['Mangools weekly rank report', ''];\n\nfor (let i = 0; i < trackingMeta.length; i++) {\n  const meta = trackingMeta[i].json;\n  const statsPayload = statsItems[i]?.json?.content?.[0]?.text;\n  const keywords = statsPayload?.keywords ?? [];\n  // SERPWatcher reports a keyword outside the top 100 as rank 101.\n  const ranked = keywords.filter((k) => typeof k.rank === 'number' && k.rank <= 100);\n  const avg = ranked.length\n    ? (ranked.reduce((sum, k) => sum + k.rank, 0) / ranked.length).toFixed(1)\n    : null;\n  // SERPWatcher reports rank_change as new rank minus old rank, so a negative value is an improvement.\n  const up = keywords.filter((k) => typeof k.rank_change === 'number' && k.rank_change < 0).length;\n  const down = keywords.filter((k) => typeof k.rank_change === 'number' && k.rank_change > 0).length;\n\n  lines.push(`${meta.domain} (${meta.location}, ${meta.device}): ${meta.keywords_count} ${meta.keywords_count === 1 ? 'keyword' : 'keywords'} tracked`);\n  lines.push(\n    avg !== null\n      ? `  ${ranked.length} of ${keywords.length} in the top 100, average position ${avg}, ${up} up and ${down} down over the last 7 days`\n      : `  none of ${keywords.length} in the top 100, ${up} up and ${down} down over the last 7 days`\n  );\n  lines.push('');\n}\n\nreturn [{ json: { summary_text: lines.join('\\n') } }];"
      },
      "id": "0ec1f6b3-1d3e-4a06-9f6b-6a2c4a5a1b01",
      "name": "Build weekly summary",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "content": "## Send it somewhere\nConnect a **Slack**, **Gmail** or **Send Email** node here to receive the `summary_text` from **Build weekly summary**.",
        "height": 160,
        "width": 300
      },
      "id": "5e6a7b8c-9d0e-4f1a-8b2c-3d4e5f6a7b02",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        880,
        0
      ]
    }
  ],
  "connections": {
    "Every Monday 08:00": {
      "main": [
        [
          {
            "node": "List trackings (SERPWatcher)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Execute workflow’ (test run)": {
      "main": [
        [
          {
            "node": "List trackings (SERPWatcher)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List trackings (SERPWatcher)": {
      "main": [
        [
          {
            "node": "Has any trackings?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has any trackings?": {
      "main": [
        [
          {
            "node": "One item per tracking",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build weekly summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "One item per tracking": {
      "main": [
        [
          {
            "node": "Get tracking stats (SERPWatcher)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get tracking stats (SERPWatcher)": {
      "main": [
        [
          {
            "node": "Build weekly summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": null,
  "staticData": null,
  "nodeGroups": [],
  "tags": []
}
