{
  "name": "Email L4: Lead magnet signup",
  "nodes": [
    {
      "name": "Webhook",
      "webhookId": "a1f6c2d8-lead-magnet",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [-460, 0],
      "parameters": {
        "httpMethod": "POST",
        "path": "lead-magnet-signup",
        "responseMode": "responseNode",
        "options": {
          "allowedOrigins": "https://example.com"
        }
      }
    },
    {
      "name": "Rate limit",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.7,
      "position": [-240, 0],
      "parameters": {
        "operation": "executeQuery",
        "query": "WITH recent AS (\n  SELECT count(*)::int AS n FROM signup_attempts\n  WHERE ip = $1 AND attempted_at > now() - interval '1 hour'\n), logged AS (\n  INSERT INTO signup_attempts (ip) VALUES ($1)\n)\nSELECT n AS recent_attempts FROM recent;",
        "options": {
          "queryReplacement": "={{ (($json.headers['cf-connecting-ip'] || $json.headers['x-forwarded-for'] || '0.0.0.0').split(',')[0]).trim() }}"
        }
      },
      "credentials": {
        "postgres": {
          "id": "REPLACE_ME",
          "name": "Postgres"
        }
      }
    },
    {
      "name": "Accept?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [-20, 0],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c9",
              "leftValue": "={{ $('Webhook').item.json.body.website }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            },
            {
              "id": "c10",
              "leftValue": "={{ $json.recent_attempts }}",
              "rightValue": 5,
              "operator": {
                "type": "number",
                "operation": "lt"
              }
            },
            {
              "id": "c11",
              "leftValue": "={{ $('Webhook').item.json.headers.origin }}",
              "rightValue": "https://example.com",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "c12",
              "leftValue": "={{ $('Webhook').item.json.body.email }}",
              "rightValue": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
              "operator": {
                "type": "string",
                "operation": "regex"
              }
            }
          ]
        }
      }
    },
    {
      "name": "Clean signup",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.5,
      "position": [220, -120],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "c13",
              "name": "email",
              "value": "={{ $('Webhook').item.json.body.email.trim().toLowerCase() }}",
              "type": "string"
            },
            {
              "id": "c14",
              "name": "first_name",
              "value": "={{ $('Webhook').item.json.body.first_name?.trim() }}",
              "type": "string"
            },
            {
              "id": "c15",
              "name": "utm_source",
              "value": "={{ $('Webhook').item.json.body.utm_source }}",
              "type": "string"
            },
            {
              "id": "c16",
              "name": "utm_medium",
              "value": "={{ $('Webhook').item.json.body.utm_medium }}",
              "type": "string"
            },
            {
              "id": "c17",
              "name": "utm_campaign",
              "value": "={{ $('Webhook').item.json.body.utm_campaign }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "name": "Record signup",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.7,
      "position": [440, -120],
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO newsletter_signups (email, first_name, utm_source, utm_medium, utm_campaign)\nVALUES ($1, $2, $3, $4, $5)\nON CONFLICT (email) DO UPDATE SET\n  first_name = COALESCE(NULLIF(EXCLUDED.first_name, ''), newsletter_signups.first_name),\n  updated_at = now()\nRETURNING *;",
        "options": {
          "queryReplacement": "={{ [$json.email, $json.first_name, $json.utm_source, $json.utm_medium, $json.utm_campaign] }}"
        }
      },
      "credentials": {
        "postgres": {
          "id": "REPLACE_ME",
          "name": "Postgres"
        }
      }
    },
    {
      "name": "Create Beehiiv subscription",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [660, -120],
      "parameters": {
        "method": "POST",
        "url": "https://api.beehiiv.com/v2/publications/pub_00000000-0000-0000-0000-000000000000/subscriptions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"email\": \"{{ $('Clean signup').item.json.email }}\",\n  \"send_welcome_email\": false,\n  \"utm_source\": \"{{ $('Clean signup').item.json.utm_source }}\",\n  \"utm_medium\": \"{{ $('Clean signup').item.json.utm_medium }}\",\n  \"utm_campaign\": \"{{ $('Clean signup').item.json.utm_campaign }}\",\n  \"custom_fields\": [\n    {\n      \"name\": \"First Name\",\n      \"value\": \"{{ $('Clean signup').item.json.first_name }}\"\n    }\n  ]\n}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "REPLACE_ME",
          "name": "Beehiiv API"
        }
      }
    },
    {
      "name": "Save Beehiiv status",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.7,
      "position": [880, -120],
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE newsletter_signups SET beehiiv_status = $2, updated_at = now()\nWHERE email = $1\nRETURNING id, email;",
        "options": {
          "queryReplacement": "={{ [$('Clean signup').item.json.email, $json.data.status] }}"
        }
      },
      "credentials": {
        "postgres": {
          "id": "REPLACE_ME",
          "name": "Postgres"
        }
      }
    },
    {
      "name": "Respond — check your email",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [1100, -120],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ ok: true, message: \"Check your email to confirm your subscription.\" }) }}",
        "options": {}
      }
    },
    {
      "name": "Respond — generic success",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [220, 120],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ ok: true, message: \"Check your email to confirm your subscription.\" }) }}",
        "options": {}
      }
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Rate limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rate limit": {
      "main": [
        [
          {
            "node": "Accept?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Accept?": {
      "main": [
        [
          {
            "node": "Clean signup",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond — generic success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean signup": {
      "main": [
        [
          {
            "node": "Record signup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Record signup": {
      "main": [
        [
          {
            "node": "Create Beehiiv subscription",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Beehiiv subscription": {
      "main": [
        [
          {
            "node": "Save Beehiiv status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Beehiiv status": {
      "main": [
        [
          {
            "node": "Respond — check your email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {}
}
