{
  "id": "O7r01ufW43h1F676",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Qualify Facebook lead ads with an AI voice agent and Supabase",
  "tags": [],
  "nodes": [
    {
      "id": "8db276c5-d950-47c3-9991-d96d848cc3ba",
      "name": "New Facebook Lead",
      "type": "n8n-nodes-base.facebookLeadAdsTrigger",
      "position": [
        784,
        480
      ],
      "parameters": {
        "form": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "page": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "options": {
          "simplifyOutput": true
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6015e11f-b666-49d6-851a-7a8ee296a6cc",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        1008,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-1",
              "name": "elevenlabs_agent_id",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__Your ElevenLabs Conversational AI agent ID__>"
            },
            {
              "id": "cfg-2",
              "name": "elevenlabs_phone_number_id",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__Your ElevenLabs phone number ID (Twilio-linked)__>"
            },
            {
              "id": "cfg-3",
              "name": "business_timezone",
              "type": "string",
              "value": "Europe/Paris"
            },
            {
              "id": "cfg-4",
              "name": "call_window_start_hour",
              "type": "number",
              "value": 9
            },
            {
              "id": "cfg-5",
              "name": "call_window_end_hour",
              "type": "number",
              "value": 19
            },
            {
              "id": "cfg-6",
              "name": "notification_email",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__Where the team should receive lead notifications__>"
            },
            {
              "id": "cfg-7",
              "name": "supabase_leads_table",
              "type": "string",
              "value": "leads"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "33071a3c-498a-42c5-8a90-a9ae1118d6cf",
      "name": "Format Lead Data",
      "type": "n8n-nodes-base.set",
      "position": [
        1232,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f1",
              "name": "fb_lead_id",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.id }}"
            },
            {
              "id": "f2",
              "name": "full_name",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.data.full_name }}"
            },
            {
              "id": "f3",
              "name": "email",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.data.email }}"
            },
            {
              "id": "f4",
              "name": "phone",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.data.phone_number }}"
            },
            {
              "id": "f5",
              "name": "company_name",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.data.company_name }}"
            },
            {
              "id": "f6",
              "name": "status",
              "type": "string",
              "value": "new"
            },
            {
              "id": "f7",
              "name": "fb_form_id",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.form_id }}"
            },
            {
              "id": "f8",
              "name": "ad_id",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.data.ad_id ?? '' }}"
            },
            {
              "id": "f9",
              "name": "campaign_id",
              "type": "string",
              "value": "={{ $('New Facebook Lead').item.json.data.campaign_id ?? '' }}"
            },
            {
              "id": "f10",
              "name": "platform",
              "type": "string",
              "value": "facebook"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f2c496f0-f612-4c59-901b-7440981cbccd",
      "name": "Check Existing Lead",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1440,
        480
      ],
      "parameters": {
        "limit": 1,
        "filters": {
          "conditions": [
            {
              "keyName": "fb_lead_id",
              "keyValue": "={{ $('Format Lead Data').item.json.fb_lead_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "={{ $('Configuration').item.json.supabase_leads_table }}",
        "operation": "getAll"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "abd2ede7-a62e-4ea7-a1ad-feff569944cd",
      "name": "Is New Lead?",
      "type": "n8n-nodes-base.if",
      "position": [
        1664,
        480
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-new",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ Object.keys($json).length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "bdab04ee-950c-4177-9328-2f82ec39dc99",
      "name": "Insert Lead",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1888,
        384
      ],
      "parameters": {
        "tableId": "={{ $('Configuration').item.json.supabase_leads_table }}",
        "dataToSend": "autoMapInputData"
      },
      "typeVersion": 1
    },
    {
      "id": "d507803d-ae9a-44bd-9fc9-c0f2f3eb2007",
      "name": "Within Calling Hours?",
      "type": "n8n-nodes-base.if",
      "position": [
        2112,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cw-1",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $now.setZone($('Configuration').item.json.business_timezone).hour }}",
              "rightValue": "={{ $('Configuration').item.json.call_window_start_hour }}"
            },
            {
              "id": "cw-2",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $now.setZone($('Configuration').item.json.business_timezone).hour }}",
              "rightValue": "={{ $('Configuration').item.json.call_window_end_hour }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "70826587-7854-472d-ac5a-47fcd84d8af1",
      "name": "Trigger ElevenLabs Call",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        2320,
        384
      ],
      "parameters": {
        "url": "https://api.elevenlabs.io/v1/convai/twilio/outbound-call",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"agent_id\": \"{{ $('Configuration').item.json.elevenlabs_agent_id }}\",\n  \"agent_phone_number_id\": \"{{ $('Configuration').item.json.elevenlabs_phone_number_id }}\",\n  \"to_number\": \"{{ $('Format Lead Data').item.json.phone }}\",\n  \"conversation_initiation_client_data\": {\n    \"dynamic_variables\": {\n      \"full_name\": {{ JSON.stringify($('Format Lead Data').item.json.full_name) }},\n      \"company_name\": {{ JSON.stringify($('Format Lead Data').item.json.company_name) }},\n      \"email\": {{ JSON.stringify($('Format Lead Data').item.json.email) }}\n    }\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "id": "c4984349-d5d0-4073-bc25-5cfcf245f9ae",
      "name": "Save Call ID",
      "type": "n8n-nodes-base.supabase",
      "position": [
        2544,
        384
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "fb_lead_id",
              "keyValue": "={{ $('Format Lead Data').item.json.fb_lead_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "={{ $('Configuration').item.json.supabase_leads_table }}",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "call_id",
              "fieldValue": "={{ $json.conversation_id }}"
            },
            {
              "fieldId": "call_status",
              "fieldValue": "in_progress"
            },
            {
              "fieldId": "status",
              "fieldValue": "calling"
            },
            {
              "fieldId": "call_started_at",
              "fieldValue": "={{ $now.toISO() }}"
            }
          ]
        },
        "operation": "update"
      },
      "typeVersion": 1
    },
    {
      "id": "923e715f-b4c2-4686-a569-86865e127221",
      "name": "Log Call Failure",
      "type": "n8n-nodes-base.supabase",
      "position": [
        2544,
        144
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "fb_lead_id",
              "keyValue": "={{ $('Format Lead Data').item.json.fb_lead_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "={{ $('Configuration').item.json.supabase_leads_table }}",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "call_status",
              "fieldValue": "failed"
            },
            {
              "fieldId": "status",
              "fieldValue": "call_failed"
            },
            {
              "fieldId": "call_error",
              "fieldValue": "={{ $json.error?.message ?? $json.message ?? 'Unknown error calling ElevenLabs' }}"
            }
          ]
        },
        "operation": "update"
      },
      "typeVersion": 1
    },
    {
      "id": "b6d9990f-b887-452a-9230-9f84b53b0140",
      "name": "Notify Team: Call Failed",
      "type": "n8n-nodes-base.slack",
      "position": [
        2768,
        144
      ],
      "parameters": {
        "text": "={{ '\u26a0\ufe0f Outbound call failed for ' + $('Format Lead Data').item.json.full_name + ' (' + $('Format Lead Data').item.json.company_name + ')\\nPhone: ' + $('Format Lead Data').item.json.phone + '\\nPlease call this lead manually.' }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.5
    },
    {
      "id": "cfe106f4-a67b-433d-b129-ebf2a46ff13a",
      "name": "Mark Lead Queued (After Hours)",
      "type": "n8n-nodes-base.supabase",
      "position": [
        2320,
        560
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "fb_lead_id",
              "keyValue": "={{ $('Format Lead Data').item.json.fb_lead_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "={{ $('Configuration').item.json.supabase_leads_table }}",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "status",
              "fieldValue": "queued_after_hours"
            },
            {
              "fieldId": "call_status",
              "fieldValue": "pending_manual_callback"
            }
          ]
        },
        "operation": "update"
      },
      "typeVersion": 1
    },
    {
      "id": "d459a858-9890-4a00-b6f1-90b855dfbf74",
      "name": "Notify Team: After-Hours Lead",
      "type": "n8n-nodes-base.slack",
      "position": [
        2544,
        560
      ],
      "parameters": {
        "text": "={{ '\ud83d\udcc5 New lead outside calling hours: ' + $('Format Lead Data').item.json.full_name + ' (' + $('Format Lead Data').item.json.company_name + ')\\nPhone: ' + $('Format Lead Data').item.json.phone + '\\nSaved to Supabase, needs a manual callback tomorrow during business hours.' }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.5
    },
    {
      "id": "d9d481d8-c562-49ed-a982-808922f896f7",
      "name": "Skip: Duplicate Lead",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1888,
        624
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "bad8f6ba-7eed-4eca-9489-b486aad37baf",
      "name": "ElevenLabs Call Complete",
      "type": "n8n-nodes-base.webhook",
      "position": [
        784,
        1280
      ],
      "parameters": {
        "path": "elevenlabs-call-complete",
        "options": {
          "rawBody": true,
          "responseCode": {
            "values": {}
          }
        },
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "9506052e-2208-4434-b381-830d2fccd103",
      "name": "Notification Settings",
      "type": "n8n-nodes-base.set",
      "position": [
        1008,
        1280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ns-1",
              "name": "notification_email",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__Where the team should receive call results__>"
            },
            {
              "id": "ns-2",
              "name": "supabase_leads_table",
              "type": "string",
              "value": "leads"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "e76df258-845b-4a80-85dc-e9d598d3d340",
      "name": "Extract Call Data",
      "type": "n8n-nodes-base.set",
      "position": [
        1232,
        1280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e1",
              "name": "conversation_id",
              "type": "string",
              "value": "={{ $json.body?.data?.conversation_id ?? $json.data?.conversation_id ?? \"\" }}"
            },
            {
              "id": "e2",
              "name": "phone_called",
              "type": "string",
              "value": "={{ $json.body?.data?.metadata?.phone_call?.external_number ?? \"\" }}"
            },
            {
              "id": "e3",
              "name": "call_duration_secs",
              "type": "number",
              "value": "={{ $json.body?.data?.metadata?.call_duration_secs ?? 0 }}"
            },
            {
              "id": "e4",
              "name": "call_terminate_reason",
              "type": "string",
              "value": "={{ $json.body?.data?.metadata?.termination_reason ?? \"\" }}"
            },
            {
              "id": "e5",
              "name": "call_successful",
              "type": "string",
              "value": "={{ $json.body?.data?.analysis?.call_successful ?? \"\" }}"
            },
            {
              "id": "e6",
              "name": "call_summary",
              "type": "string",
              "value": "={{ $json.body?.data?.analysis?.transcript_summary ?? \"\" }}"
            },
            {
              "id": "e7",
              "name": "qualification_status",
              "type": "string",
              "value": "={{ $json.body?.data?.analysis?.data_collection_results?.qualification_status?.value ?? \"unclear\" }}"
            },
            {
              "id": "e8",
              "name": "appointment_booked",
              "type": "string",
              "value": "={{ $json.body?.data?.analysis?.evaluation_criteria_results?.appointment_booked?.result ?? \"unknown\" }}"
            },
            {
              "id": "e9",
              "name": "lead_name",
              "type": "string",
              "value": "={{ $json.body?.data?.conversation_initiation_client_data?.dynamic_variables?.full_name ?? \"\" }}"
            },
            {
              "id": "e10",
              "name": "lead_email",
              "type": "string",
              "value": "={{ $json.body?.data?.conversation_initiation_client_data?.dynamic_variables?.email ?? \"\" }}"
            },
            {
              "id": "e11",
              "name": "lead_company",
              "type": "string",
              "value": "={{ $json.body?.data?.conversation_initiation_client_data?.dynamic_variables?.company_name ?? \"\" }}"
            },
            {
              "id": "e12",
              "name": "call_started_at",
              "type": "string",
              "value": "={{ $json.body?.data?.metadata?.start_time_unix_secs ? new Date($json.body.data.metadata.start_time_unix_secs * 1000).toISOString() : \"\" }}"
            },
            {
              "id": "e13",
              "name": "call_ended_at",
              "type": "string",
              "value": "={{ ($json.body?.data?.metadata?.start_time_unix_secs && $json.body?.data?.metadata?.call_duration_secs) ? new Date(($json.body.data.metadata.start_time_unix_secs + $json.body.data.metadata.call_duration_secs) * 1000).toISOString() : \"\" }}"
            },
            {
              "id": "e14",
              "name": "transcript_text",
              "type": "string",
              "value": "={{ ($json.body?.data?.transcript ?? []).map(t => t.role.toUpperCase() + \": \" + t.message).join(\"\\n\\n\") }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "960aa32e-8800-4d08-a81e-e01cb803327a",
      "name": "Update Lead Row",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1440,
        1280
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "call_id",
              "keyValue": "={{ $json.conversation_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "={{ $('Notification Settings').item.json.supabase_leads_table }}",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "call_status",
              "fieldValue": "completed"
            },
            {
              "fieldId": "status",
              "fieldValue": "={{ $json.appointment_booked === \"success\" ? \"booked\" : ($json.qualification_status === \"qualified\" ? \"qualified\" : \"reviewed\") }}"
            },
            {
              "fieldId": "call_started_at",
              "fieldValue": "={{ $json.call_started_at }}"
            },
            {
              "fieldId": "call_ended_at",
              "fieldValue": "={{ $json.call_ended_at }}"
            },
            {
              "fieldId": "call_duration_seconds",
              "fieldValue": "={{ $json.call_duration_secs }}"
            },
            {
              "fieldId": "transcript",
              "fieldValue": "={{ $json.transcript_text }}"
            },
            {
              "fieldId": "call_summary",
              "fieldValue": "={{ $json.call_summary }}"
            },
            {
              "fieldId": "sales_qualified",
              "fieldValue": "={{ $json.qualification_status }}"
            },
            {
              "fieldId": "appointment_booked",
              "fieldValue": "={{ $json.appointment_booked }}"
            },
            {
              "fieldId": "call_terminate_reason",
              "fieldValue": "={{ $json.call_terminate_reason }}"
            },
            {
              "fieldId": "call_successful",
              "fieldValue": "={{ $json.call_successful }}"
            }
          ]
        },
        "operation": "update"
      },
      "typeVersion": 1
    },
    {
      "id": "73486620-5f11-4603-b4a2-21f49526f192",
      "name": "Route by Outcome",
      "type": "n8n-nodes-base.switch",
      "position": [
        1664,
        1280
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "r0",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Extract Call Data').item.json.appointment_booked }}",
                    "rightValue": "success"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "r1a",
                    "operator": {
                      "type": "string",
                      "operation": "notEquals"
                    },
                    "leftValue": "={{ $('Extract Call Data').item.json.appointment_booked }}",
                    "rightValue": "success"
                  },
                  {
                    "id": "r1b",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Extract Call Data').item.json.qualification_status }}",
                    "rightValue": "qualified"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Other"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "18ccedf9-d7ab-4dda-8dc8-50617e2ee11f",
      "name": "Slack: Booked",
      "type": "n8n-nodes-base.slack",
      "position": [
        1888,
        1120
      ],
      "parameters": {
        "text": "={{ '\ud83c\udf89 Discovery call booked with ' + $('Extract Call Data').item.json.lead_name + ' (' + $('Extract Call Data').item.json.lead_company + ')\\nPhone: ' + $('Extract Call Data').item.json.phone_called + '\\nSummary: ' + $('Extract Call Data').item.json.call_summary }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.5
    },
    {
      "id": "cd0bc12f-9550-4cfd-bc83-0a0c52e415f5",
      "name": "Email: Booked",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2112,
        1120
      ],
      "parameters": {
        "sendTo": "={{ $('Notification Settings').item.json.notification_email }}",
        "message": "={{ '<h2>Discovery Call Booked</h2><p><strong>Lead:</strong> ' + $('Extract Call Data').item.json.lead_name + '</p><p><strong>Company:</strong> ' + $('Extract Call Data').item.json.lead_company + '</p><p><strong>Phone:</strong> ' + $('Extract Call Data').item.json.phone_called + '</p><p><strong>Summary:</strong> ' + $('Extract Call Data').item.json.call_summary + '</p><h3>Transcript</h3><pre>' + $('Extract Call Data').item.json.transcript_text + '</pre>' }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ '\ud83c\udf89 ' + $('Extract Call Data').item.json.lead_name + ' (' + $('Extract Call Data').item.json.lead_company + ') \u2014 Discovery Call Booked' }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "435031b9-2a65-4ddb-8a97-c9cb07b0f85a",
      "name": "Slack: Hot Lead",
      "type": "n8n-nodes-base.slack",
      "position": [
        1888,
        1280
      ],
      "parameters": {
        "text": "={{ '\ud83d\udd25 Qualified lead, no appointment yet: ' + $('Extract Call Data').item.json.lead_name + ' (' + $('Extract Call Data').item.json.lead_company + ')\\nPhone: ' + $('Extract Call Data').item.json.phone_called + '\\nFollow up today.\\nSummary: ' + $('Extract Call Data').item.json.call_summary }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.5
    },
    {
      "id": "a84ba405-521c-419c-b096-dabe7a052f6b",
      "name": "Email: Hot Lead Follow Up",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2112,
        1280
      ],
      "parameters": {
        "sendTo": "={{ $('Notification Settings').item.json.notification_email }}",
        "message": "={{ '<h2>Qualified Lead \u2014 Follow Up Today</h2><p><strong>Lead:</strong> ' + $('Extract Call Data').item.json.lead_name + '</p><p><strong>Company:</strong> ' + $('Extract Call Data').item.json.lead_company + '</p><p><strong>Phone:</strong> ' + $('Extract Call Data').item.json.phone_called + '</p><p><strong>Summary:</strong> ' + $('Extract Call Data').item.json.call_summary + '</p><h3>Transcript</h3><pre>' + $('Extract Call Data').item.json.transcript_text + '</pre>' }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ '\ud83d\udd25 Hot Lead \u2014 ' + $('Extract Call Data').item.json.lead_name + ' (' + $('Extract Call Data').item.json.lead_company + ')' }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8b45b98b-3569-4077-a40f-9eb8b77bf19d",
      "name": "Slack: Call Completed (Other)",
      "type": "n8n-nodes-base.slack",
      "position": [
        1888,
        1440
      ],
      "parameters": {
        "text": "={{ '\ud83d\udcde Call completed, not qualified or unclear: ' + $('Extract Call Data').item.json.lead_name + ' (' + $('Extract Call Data').item.json.lead_company + ')\\nPhone: ' + $('Extract Call Data').item.json.phone_called + '\\nReason: ' + $('Extract Call Data').item.json.call_terminate_reason + '\\nSummary: ' + $('Extract Call Data').item.json.call_summary }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.5
    },
    {
      "id": "ec3ac2c2-bda9-4b1e-a808-8fad74e84e37",
      "name": "Setup Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        64
      ],
      "parameters": {
        "color": 4,
        "width": 720,
        "height": 1788,
        "content": "# Qualify Facebook lead ads with an AI voice agent and Supabase\n# \ud83d\udce5  [Open full documentation on Notion](https://automatisation.notion.site/Course-Qualify-Facebook-lead-ads-with-an-AI-voice-agent-and-Supabase-3a03d6550fd98175864fc792bb2b0671)\n\n## How it works\nAs soon as someone submits a Facebook Lead Ads form, this workflow saves the lead to Supabase, checks it is not a duplicate, and (if inside your calling hours) instantly triggers an outbound AI voice call with ElevenLabs Conversational AI to qualify the lead and try to book a meeting. When the call ends, ElevenLabs posts the results back via webhook: the lead row is updated in Supabase and the team gets a Slack + email notification tailored to the outcome (booked / hot lead / other).\n\n## Setup\n1. Import this workflow into n8n.\n2. Add credentials: Facebook Lead Ads, ElevenLabs (Header Auth), Supabase, Slack, Gmail.\n3. Select your Facebook Page and Lead Form on the trigger.\n4. Fill in the Configuration node: ElevenLabs agent ID, phone number ID, your calling-hours window and timezone, and your notification email.\n5. Select your Slack channel on every Slack node, and pick your Supabase table.\n6. Copy the ElevenLabs webhook URL from \"ElevenLabs Call Complete\" into your ElevenLabs agent post-call webhook settings.\n7. Activate the workflow.\n\n## Requirements\n1. Facebook Ads account with a Lead Ads form connected to a Business Page\n2. ElevenLabs Conversational AI account with a configured voice agent and phone number\n3. Supabase project with a `leads` table (see Notion doc for the schema)\n4. Slack workspace with a bot invited to your notification channel\n5. Gmail account\n\n## Customization\n- Adjust the calling-hours window and timezone in Configuration to match your compliance needs.\n- Add more Switch branches in \"Route by Outcome\" for finer lead scoring.\n- Swap Slack/Gmail for your own CRM or ticketing tool.\n\nNeed help customizing?\nContact me for consulting and support : [Linkedin](https://www.linkedin.com/in/doctor-firass/)\n\n# MY NEW YOUTUBE CHANNEL\n\ud83d\udc49 [Subscribe to my new YouTube channel](https://www.youtube.com/@DrFiras_AI). Here I'll share videos and Shorts with practical tutorials and FREE templates for n8n.\n\n[![The AI Doctor](https://www.dr-firas.com/the-ai-doctor.png)](https://www.youtube.com/@DrFiras_AI)"
      },
      "typeVersion": 1
    },
    {
      "id": "8e04f894-1794-4589-ab58-2840c269401d",
      "name": "Workflow A Header",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        752,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 1508,
        "height": 200,
        "content": "## Workflow A: Lead intake, dedup check, calling-hours gate and outbound call\n\nFires in real time on a new Facebook lead. Saves it to Supabase (skipping duplicates), and if inside calling hours, launches an ElevenLabs AI voice call. Outside calling hours or on call failure, the team is notified for manual follow-up."
      },
      "typeVersion": 1
    },
    {
      "id": "3db4000e-9403-455d-a362-4458390b2193",
      "name": "Workflow B Header",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        768,
        864
      ],
      "parameters": {
        "color": 7,
        "width": 1500,
        "height": 216,
        "content": "## Workflow B: Post-call analysis, lead update and outcome-based notification\n\n1. Listens for the ElevenLabs post-call webhook\n2. Extracts qualification, booking, transcript and summary\n3. Updates the Supabase lead row\n4. Routes by outcome (Booked / Qualified not booked / Other)\n5. Sends a tailored Slack + email notification per branch"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "7dfb3044-d51c-416f-ba6a-db23acd6cc39",
  "nodeGroups": [],
  "connections": {
    "Insert Lead": {
      "main": [
        [
          {
            "node": "Within Calling Hours?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is New Lead?": {
      "main": [
        [
          {
            "node": "Insert Lead",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip: Duplicate Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configuration": {
      "main": [
        [
          {
            "node": "Format Lead Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack: Booked": {
      "main": [
        [
          {
            "node": "Email: Booked",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack: Hot Lead": {
      "main": [
        [
          {
            "node": "Email: Hot Lead Follow Up",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Lead Row": {
      "main": [
        [
          {
            "node": "Route by Outcome",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Lead Data": {
      "main": [
        [
          {
            "node": "Check Existing Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Call Failure": {
      "main": [
        [
          {
            "node": "Notify Team: Call Failed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Outcome": {
      "main": [
        [
          {
            "node": "Slack: Booked",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack: Hot Lead",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack: Call Completed (Other)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Call Data": {
      "main": [
        [
          {
            "node": "Update Lead Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Facebook Lead": {
      "main": [
        [
          {
            "node": "Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Existing Lead": {
      "main": [
        [
          {
            "node": "Is New Lead?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notification Settings": {
      "main": [
        [
          {
            "node": "Extract Call Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Within Calling Hours?": {
      "main": [
        [
          {
            "node": "Trigger ElevenLabs Call",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Lead Queued (After Hours)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger ElevenLabs Call": {
      "main": [
        [
          {
            "node": "Save Call ID",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Call Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ElevenLabs Call Complete": {
      "main": [
        [
          {
            "node": "Notification Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Lead Queued (After Hours)": {
      "main": [
        [
          {
            "node": "Notify Team: After-Hours Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}