{
  "id": "mXgQJT7qXMEFQAow",
  "name": "Server-Side Meta Ads Tracking Template [PUBLIC]",
  "tags": [],
  "nodes": [
    {
      "id": "de88e89c-acfd-4592-8f73-0f1b56dba93b",
      "name": "Edit Normalize PII",
      "type": "n8n-nodes-base.set",
      "position": [
        -752,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9545094c-a24a-4689-b212-4bc351f8f08b",
              "name": "normalized_email",
              "type": "string",
              "value": "={{ $json.body.email.trim().toLowerCase() }}"
            },
            {
              "id": "fe26118b-5e9e-4c3f-acf0-e995a32779d1",
              "name": "normalized_phone",
              "type": "string",
              "value": "={{ $json.body.phone.replace(/\\D/g, '') }}"
            },
            {
              "id": "59a2b784-44c4-44c4-bf28-2e8a27cc8975",
              "name": "firstName",
              "type": "string",
              "value": "={{ $json.body.firstName.trim().toLowerCase() }}"
            },
            {
              "id": "72ada7ed-e895-445e-ac4f-f5d8102ba46a",
              "name": "lastName",
              "type": "string",
              "value": "={{ $json.body.lastName.trim().toLowerCase() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cf2debc3-7cc0-450f-9e58-9b981333c537",
      "name": "Crypto - Hash Email",
      "type": "n8n-nodes-base.crypto",
      "position": [
        -512,
        0
      ],
      "parameters": {
        "type": "SHA256",
        "value": "={{ $json.normalized_email }}",
        "dataPropertyName": "hashed_em"
      },
      "typeVersion": 1
    },
    {
      "id": "b6821a25-cbb2-4083-9693-30cf3da3aaac",
      "name": "Crypto - Hash Phone",
      "type": "n8n-nodes-base.crypto",
      "position": [
        -256,
        0
      ],
      "parameters": {
        "type": "SHA256",
        "value": "={{ $json.normalized_phone }}",
        "dataPropertyName": "hashed_ph"
      },
      "typeVersion": 1
    },
    {
      "id": "1a61578d-b32a-41f8-9e24-a635a645eda0",
      "name": "Set - Compute Timestamps & Map Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        400,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c2ccdb0e-05c6-4f02-9daf-c495a261d82a",
              "name": "conversion_timestamp",
              "type": "number",
              "value": "={{ Math.floor(Date.now() / 1000) }}"
            },
            {
              "id": "a434a6c6-c4fe-48a1-b808-58cf42378f1d",
              "name": "event_name",
              "type": "string",
              "value": "SubmitApplication"
            },
            {
              "id": "1323fcc0-95e8-461b-9cb5-f0106b10345d",
              "name": "hashed_em",
              "type": "string",
              "value": "={{ $('Crypto - Hash Email').item.json.hashed_em }}"
            },
            {
              "id": "7a276391-9aab-41a1-8514-63b0c5350011",
              "name": "hashed_ph",
              "type": "string",
              "value": "={{ $json.hashed_ph }}"
            },
            {
              "id": "19d9b649-873f-4018-b7b9-a7070143abb1",
              "name": "hashed_firstName",
              "type": "string",
              "value": "={{ $json.hashed_firstName }}"
            },
            {
              "id": "15d5a6d2-6c71-40a4-8ad8-fe929d94e9b4",
              "name": "hashed_lastName",
              "type": "string",
              "value": "={{ $json.hashed_lastName }}"
            },
            {
              "id": "dda7617f-a148-4b8f-9459-50baa386507e",
              "name": "fbc",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.fbc }}"
            },
            {
              "id": "fab3e276-ead2-4654-ae09-5f6f3bcef3e6",
              "name": "fbp",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.fbp }}"
            },
            {
              "id": "8bf3b47f-f737-4262-8f86-27f287ed6560",
              "name": "ipAddress",
              "type": "string",
              "value": "={{ $('Webhook').item.json.headers['x-forwarded-for'] }}"
            },
            {
              "id": "4f88bdd9-d7cf-4f8e-84b3-db55f50e10ed",
              "name": "userAgent",
              "type": "string",
              "value": "={{ $('Webhook').item.json.headers['user-agent'] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "13f09e7a-7684-41d1-9396-413f71727703",
      "name": "Crypto - First Name",
      "type": "n8n-nodes-base.crypto",
      "position": [
        -48,
        0
      ],
      "parameters": {
        "type": "SHA256",
        "value": "={{ $json.firstName }}",
        "dataPropertyName": "hashed_firstName"
      },
      "typeVersion": 1
    },
    {
      "id": "798bdcb5-3861-4a9a-a355-a776e510773c",
      "name": "Crypto - Last Name",
      "type": "n8n-nodes-base.crypto",
      "position": [
        160,
        0
      ],
      "parameters": {
        "type": "SHA256",
        "value": "={{ $json.lastName }}",
        "dataPropertyName": "hashed_lastName"
      },
      "typeVersion": 1
    },
    {
      "id": "9f465c29-2bfd-443f-8bc9-ba259f3d5751",
      "name": "Sending Events To Facebook Pixel",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        864,
        0
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v24.0/PIXEL_ID_HERE/events",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9df179f5-643b-4a2e-8a51-fd407b16183d",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -976,
        0
      ],
      "parameters": {
        "path": "meta-conversion-api",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "7a962bb1-7d34-46b5-82d7-3f777ee9ad4f",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1072,
        0
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "allIncomingItems"
      },
      "typeVersion": 1.4
    },
    {
      "id": "2b5d641f-7cb4-4a2e-b708-66dbf56396c0",
      "name": "Preparing for HTTP Request Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        0
      ],
      "parameters": {
        "jsCode": "// Get the incoming data from the previous node.\n// n8n provides this as the '$json' variable.\nconst incomingData = $json;\n\n// Create the final, perfectly structured payload for the Facebook CAPI node.\nconst capiPayload = {\n  data: [\n    {\n      event_name: incomingData.event_name,\n      event_time: incomingData.conversion_timestamp,\n      action_source: 'website',\n\n      // Build the user_data object by mapping your fields to Meta's fields.\n      user_data: {\n        // --- These are the two lines we are fixing ---\n        // We are now 100% sure they match your input data.\n        fn: incomingData.hashed_firstName,\n        ln: incomingData.hashed_lastName,\n\n        // The rest of the mapping\n        em: incomingData.hashed_em,\n        ph: incomingData.hashed_ph,\n        fbc: incomingData.fbc,\n        fbp: incomingData.fbp,\n        client_ip_address: incomingData.ipAddress,\n        client_user_agent: incomingData.userAgent,\n      },\n    },\n  ],\n};\n\n// Return the transformed data so the next node can use it.\nreturn capiPayload;"
      },
      "typeVersion": 2
    },
    {
      "id": "39e00abc-81c2-475c-b084-9fe1b1db8771",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1840,
        -448
      ],
      "parameters": {
        "width": 592,
        "height": 880,
        "content": "## Send Server-Side Conversions to the Meta Ads API (CAPI)\n\nThis workflow acts as a server-side endpoint to send conversion events directly to the Meta (Facebook) Conversions API. This helps you get more accurate ad tracking that isn't affected by browser ad blockers or iOS privacy changes.\n\n**Watch the full setup tutorial on YouTube:**\nhttps://youtu.be/_fdMPIYEvFM\n\n## How it works\n1.  **Webhook Trigger:** It starts when it receives data at its unique URL.\n2.  **Normalize & Hash PII:** It cleans up the user data (email, phone, etc.) and securely hashes it using SHA-256, as required by Meta.\n3.  **Format Payload:** It assembles the hashed data, event details, and browser info (`fbc`, `fbp`, IP address) into a perfectly structured payload for the CAPI.\n4.  **Send to Meta:** It sends the final data directly to Meta's servers.\n\n## \u26a0\ufe0f How to set up\n### Step 1: Configure Your Data Source\nThis workflow is triggered by a Webhook. You need to send data to it from your website form, CRM, or backend. The data **MUST** be sent as a JSON object.\n\nThe required fields are `email`, `phone`, `firstName`, `lastName`, `fbc`, and `fbp`. For a live example of the data structure, please see the **pinned data on the Webhook node**.\n\n### Step 2: Configure the Workflow\n1.  **Copy the Webhook URL:** Click on the \"Webhook\" trigger node and copy the **Test URL** for testing, or the **Production URL** for your live application.\n2.  **Customize Event Name (Optional):** In the \"Set - Compute Timestamps & Map Fields\" node, you can change the `event_name` from `SubmitApplication` to whatever you need (e.g., `Purchase`, `Lead`).\n3.  **Add Your Meta Pixel ID:** In the final \"Sending Events To Facebook Pixel\" node, replace `PIXEL_ID_HERE` in the **URL** with your actual Meta Pixel ID.\n4.  **Add Your Access Token:** In the same node, go to the **Authentication** tab and create a new **Bearer YOUR_TOKEN_HERE** credential. Paste the CAPI Access Token you generated from Meta Events Manager."
      },
      "typeVersion": 1
    },
    {
      "id": "695dd7b8-2030-4114-9e91-f426a55e0ba7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1056,
        160
      ],
      "parameters": {
        "height": 272,
        "content": "**\ud83d\udc47 STEP 1: START HERE**\n\nThis is your endpoint. Copy the URL from this node and configure your website form or backend to send a POST request with a JSON body to it.\n\nSee the main yellow note and the **pinned data on this node** for the required JSON data structure!"
      },
      "typeVersion": 1
    },
    {
      "id": "eb626055-ef90-420d-a569-715797fd6c7f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        160
      ],
      "parameters": {
        "color": 4,
        "width": 864,
        "height": 128,
        "content": "**\ud83d\udd12 STEP 2: SECURE & HASH DATA**\n\nThis section automatically cleans and hashes the incoming user data to meet Meta's CAPI requirements.\n\nNo configuration is needed here\u2014it just works!"
      },
      "typeVersion": 1
    },
    {
      "id": "018c683d-5d26-4931-9cc4-f7f8bd23aafc",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        752,
        176
      ],
      "parameters": {
        "width": 512,
        "height": 224,
        "content": "**\ud83d\ude80 STEP 3: SEND TO META**\n\nThis is the final and most important step.\n\n**Action Required:**\n1.  Replace **`PIXEL_ID_HERE`** in the **URL** with your real Meta Pixel ID.\n2.  Under **Authentication**, create a new **Bearer YOUR_TOKEN_HERE** credential and paste in your CAPI Access Token from Meta Events Manager."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "55ded24f-0574-40b7-8a5e-414ab42f5e24",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Edit Normalize PII",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crypto - Last Name": {
      "main": [
        [
          {
            "node": "Set - Compute Timestamps & Map Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Normalize PII": {
      "main": [
        [
          {
            "node": "Crypto - Hash Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crypto - First Name": {
      "main": [
        [
          {
            "node": "Crypto - Last Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crypto - Hash Email": {
      "main": [
        [
          {
            "node": "Crypto - Hash Phone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crypto - Hash Phone": {
      "main": [
        [
          {
            "node": "Crypto - First Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sending Events To Facebook Pixel": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparing for HTTP Request Payload": {
      "main": [
        [
          {
            "node": "Sending Events To Facebook Pixel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set - Compute Timestamps & Map Fields": {
      "main": [
        [
          {
            "node": "Preparing for HTTP Request Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}