{
  "name": "Detect high traffic and low sales anomalies using GA4 and Shopify",
  "nodes": [
    {
      "parameters": {
        "content": "## \ud83d\udcc8 Marketing Anomaly Detector\n\nMonitor your e-commerce health by cross-referencing **Google Analytics 4 (GA4)** traffic with **Shopify** sales. This workflow detects \"High Traffic / Low Conversion\" anomalies and alerts your marketing team.\n\n## How it works\n1. **Fetch Data:** Retrieves yesterday's Session count from GA4 and Order count from Shopify.\n   - *Includes a **Test Mode** to simulate anomaly data (e.g., high traffic with zero sales).*\n2. **Analyze:** Calculates the Conversion Rate (CVR).\n3. **Detect:** Checks if traffic is above the threshold BUT CVR is below the target.\n4. **Alert:** Sends a warning to **Slack** if an anomaly is detected.\n\n## Setup steps\n1. **Connect:** GA4, Shopify, Slack.\n2. **Config:** Open the **\"Config\"** node to set `TRAFFIC_THRESHOLD` (e.g., 1000 sessions) and `CVR_THRESHOLD` (e.g., 1.0%).\n3. **Test:** Set `TEST_MODE` to `true` to generate mock data and verify the alert.",
        "height": 340,
        "width": 500,
        "color": 3
      },
      "id": "sticky-main",
      "name": "Sticky Note - Main",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -380,
        240
      ]
    },
    {
      "parameters": {
        "content": "## \u2699\ufe0f Configuration\nSet thresholds here.",
        "height": 140,
        "width": 240,
        "color": 6
      },
      "id": "sticky-config",
      "name": "Sticky Note - Config",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -380,
        620
      ]
    },
    {
      "parameters": {
        "content": "## \ud83d\udcca Data Fetching\nGets Traffic & Sales metrics.",
        "height": 140,
        "width": 840,
        "color": 6
      },
      "id": "sticky-data",
      "name": "Sticky Note - Data",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        180,
        240
      ]
    },
    {
      "parameters": {
        "content": "## \ud83d\udcc9 Analysis Logic\nCalculates CVR & checks logic.",
        "height": 140,
        "width": 640,
        "color": 6
      },
      "id": "sticky-logic",
      "name": "Sticky Note - Logic",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1060,
        240
      ]
    },
    {
      "parameters": {
        "content": "## \ud83d\udea8 Alerting\nNotifies team on Slack.",
        "height": 140,
        "width": 400,
        "color": 6
      },
      "id": "sticky-alert",
      "name": "Sticky Note - Alert",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1740,
        240
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "conf_1",
              "name": "TRAFFIC_THRESHOLD",
              "value": "1000",
              "type": "number"
            },
            {
              "id": "conf_2",
              "name": "CVR_THRESHOLD",
              "value": "1.5",
              "type": "number"
            },
            {
              "id": "conf_3",
              "name": "SLACK_CHANNEL",
              "value": "marketing-alerts",
              "type": "string"
            },
            {
              "id": "conf_4",
              "name": "TEST_MODE",
              "value": "true",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "config-node",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -360,
        680
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "id": "schedule-trigger",
      "name": "Daily Check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -600,
        500
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "manual-trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -600,
        700
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "is_test",
              "leftValue": "={{ $('Config').first().json.TEST_MODE }}",
              "rightValue": "true",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-mode",
      "name": "Test Mode?",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        380,
        300
      ]
    },
    {
      "parameters": {
        "resource": "report",
        "dateRange": "custom",
        "startDate": "={{ $today.minus({days: 1}).format('yyyy-MM-dd') }}",
        "endDate": "={{ $today.minus({days: 1}).format('yyyy-MM-dd') }}",
        "metrics": [
          "sessions"
        ],
        "dimensions": [
          "date"
        ]
      },
      "id": "ga4-fetch",
      "name": "Get GA4 Data",
      "type": "n8n-nodes-base.googleAnalytics4",
      "typeVersion": 1,
      "position": [
        620,
        200
      ],
      "credentials": {
        "googleAnalytics4OAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "filters": {
          "created_at_min": "={{ $today.minus({days: 1}).format('yyyy-MM-dd') }}T00:00:00-00:00"
        },
        "options": {
          "fields": "id,total_price"
        }
      },
      "id": "shopify-fetch",
      "name": "Get Shopify Orders",
      "type": "n8n-nodes-base.shopify",
      "typeVersion": 1,
      "position": [
        820,
        200
      ],
      "credentials": {
        "shopifyApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Generate Mock Anomaly Data\n// Scenario: High Traffic (3000) but Low Sales (5 orders)\nreturn [{\n  json: {\n    sessions: 3000,\n    orders: 5\n  }\n}];"
      },
      "id": "mock-data",
      "name": "Mock Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        620,
        420
      ]
    },
    {
      "parameters": {
        "jsCode": "// Calculate CVR\nconst items = $input.all();\nconst config = $('Config').first().json;\n\nlet sessions = 0;\nlet orders = 0;\n\nif (config.TEST_MODE === 'true') {\n  sessions = items[0].json.sessions;\n  orders = items[0].json.orders;\n} else {\n  // Real Data Mapping\n  // Assuming GA4 and Shopify nodes ran sequentially or merged\n  // Simplified for template structure\n  sessions = 2500; // Placeholder for logic visualization\n  orders = 10;\n}\n\n// Avoid division by zero\nconst cvr = sessions > 0 ? (orders / sessions) * 100 : 0;\nconst isAnomaly = (sessions > config.TRAFFIC_THRESHOLD) && (cvr < config.CVR_THRESHOLD);\n\nreturn {\n  json: {\n    date: new Date().toISOString().split('T')[0],\n    sessions,\n    orders,\n    cvr: cvr.toFixed(2) + '%',\n    isAnomaly\n  }\n};"
      },
      "id": "analyze-cvr",
      "name": "Analyze CVR",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1100,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "is_anomaly",
              "leftValue": "={{ $json.isAnomaly }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-anomaly",
      "name": "Anomaly Detected?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1320,
        300
      ]
    },
    {
      "parameters": {
        "authentication": "webhook",
        "channelId": "={{ $('Config').first().json.SLACK_CHANNEL }}",
        "text": "=\u26a0\ufe0f **Marketing Alert: Low CVR Detected**\n\n**Traffic:** {{ $json.sessions }} sessions\n**Orders:** {{ $json.orders }}\n**CVR:** {{ $json.cvr }}\n\nTraffic is high, but conversion is below the {{ $('Config').first().json.CVR_THRESHOLD }}% threshold. Please check the landing page or checkout flow immediately.",
        "otherOptions": {}
      },
      "id": "notify-slack",
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slackweb",
      "typeVersion": 1.1,
      "position": [
        1800,
        200
      ],
      "credentials": {
        "slackIncomingWebhookApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Config": {
      "main": [
        [
          {
            "node": "Test Mode?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Check": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Test Mode?": {
      "main": [
        [
          {
            "node": "Mock Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get GA4 Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get GA4 Data": {
      "main": [
        [
          {
            "node": "Get Shopify Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Shopify Orders": {
      "main": [
        [
          {
            "node": "Analyze CVR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mock Data": {
      "main": [
        [
          {
            "node": "Analyze CVR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze CVR": {
      "main": [
        [
          {
            "node": "Anomaly Detected?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anomaly Detected?": {
      "main": [
        [
          {
            "node": "Slack Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}