{
  "name": "Nodbot - Google Sheets integration blueprint with upsert and schema guard",
  "nodes": [
    {
      "parameters": {
        "path": "integration-google-sheets-n8n",
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "id": "c38f8da1-ea16-4370-afed-fb40b892f2d9",
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        260
      ]
    },
    {
      "parameters": {
        "jsCode": "const src = $json.body ?? $json;\nconst rawPhone = String(src.phone ?? '').trim();\nlet digits = rawPhone.replace(/\\D/g, '');\nif (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`;\nif (digits.length === 10) digits = `7${digits}`;\nconst phoneNormalized = /^7\\d{10}$/.test(digits) ? `+${digits}` : '';\nconst email = String(src.email ?? '').trim().toLowerCase();\nconst externalId = String(src.external_id ?? '').trim();\nconst lookupKey = externalId || phoneNormalized || email;\nif (!lookupKey) throw new Error('No lookup key for Google Sheets upsert');\nreturn [{ json: {\n  lookup_key: lookupKey,\n  phone_raw: rawPhone,\n  phone_normalized: phoneNormalized,\n  email,\n  name: String(src.name ?? '').trim(),\n  source: src.source ?? 'unknown',\n  utm_source: src.utm_source ?? '',\n  utm_campaign: src.utm_campaign ?? '',\n  status: src.status ?? 'new',\n  updated_at: new Date().toISOString()\n}}];"
      },
      "id": "4d521cc4-fe1d-450d-97ba-5dd8c3800210",
      "name": "Normalize row",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        280,
        260
      ]
    },
    {
      "parameters": {},
      "id": "60653461-8291-4cb6-947e-8e2046263c09",
      "name": "Check required columns",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        560,
        260
      ]
    },
    {
      "parameters": {},
      "id": "1cc513e8-4e69-4d11-81ae-33c05492a780",
      "name": "Append or Update Row",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 2,
      "position": [
        840,
        260
      ]
    },
    {
      "parameters": {},
      "id": "080cb372-eb1d-468b-b83c-59a1ba62af0e",
      "name": "Audit result",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 2,
      "position": [
        1120,
        260
      ]
    },
    {
      "parameters": {},
      "id": "104f8d3f-5f1e-414c-bd25-82976cc6d634",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 2,
      "position": [
        1400,
        260
      ]
    }
  ],
  "connections": {
    "Webhook input": {
      "main": [
        [
          {
            "node": "Normalize row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize row": {
      "main": [
        [
          {
            "node": "Check required columns",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check required columns": {
      "main": [
        [
          {
            "node": "Append or Update Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append or Update Row": {
      "main": [
        [
          {
            "node": "Audit result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Audit result": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    "nodbot",
    "integration",
    "production"
  ],
  "triggerCount": 1,
  "updatedAt": "2026-05-30T00:00:00.000Z",
  "versionId": "5a3a0452-ae74-4b18-860f-9e2750f92855",
  "meta": {
    "templateCredsSetupCompleted": false
  }
}