{
  "name": "Chockstone link signup to Google Sheets",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "chockstone",
        "options": {}
      },
      "id": "6d1f0e8a-3b6a-4c1e-9a1a-0c1c8a5a1001",
      "name": "Chockstone Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "webhookId": "6d1f0e8a-3b6a-4c1e-9a1a-0c1c8a5a1001"
    },
    {
      "parameters": {
        "jsCode": "const crypto = require('crypto');\n\n// Paste the secret Chockstone showed you when you created the webhook.\nconst secret = 'whsec_PASTE_YOUR_SECRET_HERE';\n\nconst item = $input.first().json;\nconst timestamp = item.headers['chockstone-timestamp'] || '';\nconst given = item.headers['chockstone-signature'] || '';\n// Chockstone writes the body with JSON.stringify, so writing the parsed body back gives the same bytes.\nconst body = JSON.stringify(item.body);\nconst expected = 'sha256=' + crypto.createHmac('sha256', secret).update(timestamp + '.' + body).digest('hex');\nconst a = Buffer.from(expected);\nconst b = Buffer.from(given);\nconst fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;\nif (!fresh || a.length !== b.length || !crypto.timingSafeEqual(a, b)) {\n  throw new Error('Chockstone signature check failed');\n}\nreturn [{ json: item.body }];\n"
      },
      "id": "6d1f0e8a-3b6a-4c1e-9a1a-0c1c8a5a1002",
      "name": "Verify signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "6d1f0e8a-3b6a-4c1e-9a1a-0c1c8a5a1003",
              "leftValue": "={{ $json.type }}",
              "rightValue": "link.signup",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "6d1f0e8a-3b6a-4c1e-9a1a-0c1c8a5a1004",
      "name": "Is it a link signup",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        480,
        0
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "REPLACE_WITH_YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Sheet1",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "signed_up_at": "={{ $json.created_at }}",
            "page": "={{ $json.data.page_slug }}",
            "link_id": "={{ $json.data.link_id }}",
            "email_hash": "={{ $json.data.email_hash }}"
          },
          "matchingColumns": [],
          "schema": []
        },
        "options": {}
      },
      "id": "6d1f0e8a-3b6a-4c1e-9a1a-0c1c8a5a1005",
      "name": "Add a row to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        720,
        -80
      ]
    }
  ],
  "connections": {
    "Chockstone Webhook": {
      "main": [
        [
          {
            "node": "Verify signature",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify signature": {
      "main": [
        [
          {
            "node": "Is it a link signup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is it a link signup": {
      "main": [
        [
          {
            "node": "Add a row to Google Sheets",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "active": false
}
