{
  "name": "Instant Inbound Lead Auto-Responder + HubSpot CRM Sync",
  "flow": [
    {
      "id": 1,
      "module": "gateway:CustomWebHook",
      "version": 1,
      "parameters": {
        "hook": 0,
        "maxResults": 1
      },
      "mapper": {},
      "metadata": {
        "designer": { "x": 0, "y": 0 },
        "restore": {
          "parameters": {
            "hook": {
              "label": "Website lead form",
              "data": { "editable": "true" }
            }
          }
        },
        "parameters": [
          {
            "name": "hook",
            "type": "hook:gateway-webhook",
            "label": "Webhook",
            "required": true
          },
          { "name": "maxResults", "type": "number", "label": "Maximum number of results" }
        ],
        "interface": [
          { "name": "firstname", "type": "text", "label": "First name" },
          { "name": "lastname", "type": "text", "label": "Last name" },
          { "name": "email", "type": "email", "label": "Email" },
          { "name": "company", "type": "text", "label": "Company" },
          { "name": "message", "type": "text", "label": "Message" },
          { "name": "source", "type": "text", "label": "Source URL" }
        ]
      }
    },
    {
      "id": 2,
      "module": "builtin:BasicFeeder",
      "version": 1,
      "parameters": {},
      "mapper": {
        "array": "{{ if(length(trim(1.email)) > 0 and contains(1.email, \"@\"); emptyarray; emptyarray) }}"
      },
      "metadata": {
        "designer": { "x": 300, "y": 0, "name": "Validate payload" },
        "notes": "A missing or malformed email is the only thing that makes the rest of this scenario meaningless. Stop here rather than creating a junk HubSpot contact."
      }
    },
    {
      "id": 3,
      "module": "hubspotcrm:searchObjects",
      "version": 3,
      "parameters": {
        "__IMTCONN__": 0
      },
      "mapper": {
        "objectType": "contacts",
        "limit": "1",
        "filterGroups": [
          {
            "filters": [
              {
                "propertyName": "email",
                "operator": "EQ",
                "value": "{{ lower(trim(1.email)) }}"
              }
            ]
          }
        ],
        "properties": ["email", "firstname", "lastname", "company", "hs_object_id"]
      },
      "metadata": {
        "designer": { "x": 600, "y": 0, "name": "Find existing contact" },
        "notes": "Deduplication happens here, not in a router further down. Searching by lowercased email before any write is what stops the same person becoming three contacts."
      }
    },
    {
      "id": 4,
      "module": "builtin:BasicRouter",
      "version": 1,
      "mapper": null,
      "metadata": {
        "designer": { "x": 900, "y": 0, "name": "New or existing?" }
      },
      "routes": [
        {
          "flow": [
            {
              "id": 5,
              "module": "hubspotcrm:createObject",
              "version": 3,
              "parameters": { "__IMTCONN__": 0 },
              "filter": {
                "name": "Contact not found",
                "conditions": [
                  [
                    {
                      "a": "{{ 3.hs_object_id }}",
                      "o": "exist:notexist"
                    }
                  ]
                ]
              },
              "mapper": {
                "objectType": "contacts",
                "properties": {
                  "email": "{{ lower(trim(1.email)) }}",
                  "firstname": "{{ 1.firstname }}",
                  "lastname": "{{ 1.lastname }}",
                  "company": "{{ 1.company }}",
                  "hs_lead_status": "NEW",
                  "lifecyclestage": "lead"
                }
              },
              "metadata": {
                "designer": { "x": 1200, "y": -150, "name": "Create contact" }
              }
            }
          ]
        },
        {
          "flow": [
            {
              "id": 6,
              "module": "hubspotcrm:updateObject",
              "version": 3,
              "parameters": { "__IMTCONN__": 0 },
              "filter": {
                "name": "Contact already exists",
                "conditions": [
                  [
                    {
                      "a": "{{ 3.hs_object_id }}",
                      "o": "exist:exist"
                    }
                  ]
                ]
              },
              "mapper": {
                "objectType": "contacts",
                "objectId": "{{ 3.hs_object_id }}",
                "properties": {
                  "firstname": "{{ ifempty(1.firstname; 3.firstname) }}",
                  "company": "{{ ifempty(1.company; 3.company) }}"
                }
              },
              "metadata": {
                "designer": { "x": 1200, "y": 150, "name": "Update contact" },
                "notes": "ifempty() keeps whatever HubSpot already holds when the new submission left a field blank. A plain overwrite is how enrichment gets destroyed by a lazy form fill."
              }
            }
          ]
        }
      ]
    },
    {
      "id": 7,
      "module": "hubspotcrm:createEngagement",
      "version": 3,
      "parameters": { "__IMTCONN__": 0 },
      "mapper": {
        "engagementType": "NOTE",
        "associations": {
          "contactIds": ["{{ ifempty(5.id; ifempty(6.id; 3.hs_object_id)) }}"]
        },
        "metadata": {
          "body": "<p><strong>Website enquiry</strong></p><p>{{ replace(1.message; newline; \"<br>\") }}</p><hr><p>Company: {{ ifempty(1.company; \"Not given\") }}<br>Source: {{ ifempty(1.source; \"Not given\") }}<br>Received: {{ formatDate(now; \"YYYY-MM-DD HH:mm\") }}</p>"
        }
      },
      "metadata": {
        "designer": { "x": 1500, "y": 0, "name": "Log message as note" },
        "notes": "The message goes on a timeline note rather than into a custom contact property. Properties hold one value; a second enquiry from the same person would overwrite the first."
      }
    },
    {
      "id": 8,
      "module": "email:ActionSendEmail",
      "version": 5,
      "parameters": { "account": 0 },
      "mapper": {
        "to": ["{{ lower(trim(1.email)) }}"],
        "subject": "Thanks {{ ifempty(1.firstname; \"there\") }} - we have your message",
        "contentType": "html",
        "html": "<p>Hi {{ ifempty(1.firstname; \"there\") }},</p><p>Thanks for getting in touch{{ if(length(trim(1.company)) > 0; \" from \" + 1.company; \"\") }}. Your message reached us and a real person is reading it - we reply within one business day.</p><p>Here is what you sent, so you have a copy:</p><blockquote>{{ replace(1.message; newline; \"<br>\") }}</blockquote><p>If anything else comes up in the meantime, just reply to this email.</p><p>--<br>TechZapp</p>",
        "attachments": [],
        "headers": []
      },
      "metadata": {
        "designer": { "x": 1800, "y": 0, "name": "Send auto-reply (SMTP)" },
        "notes": "Sent last, on purpose. If HubSpot fails you want the run to stop before promising the sender that their message arrived somewhere it did not.",
        "parameters": [
          {
            "name": "account",
            "type": "account:email",
            "label": "SMTP connection",
            "required": true
          }
        ]
      }
    }
  ],
  "metadata": {
    "instant": true,
    "version": 1,
    "scenario": {
      "roundtrips": 1,
      "maxErrors": 3,
      "autoCommit": true,
      "autoCommitTriggerLast": true,
      "sequential": false,
      "confidential": false,
      "dataloss": false,
      "dlq": true,
      "freshVariables": false
    },
    "designer": { "orphans": [] },
    "zone": "us1.make.com",
    "notes": [
      "Import this file at Scenarios -> Create a new scenario -> ... -> Import Blueprint.",
      "Three things must be set after import, because connections and hook ids are never portable: the Webhook (module 1), the HubSpot connection (modules 3-7), and the SMTP connection (module 8).",
      "Module 8 is a generic SMTP send, so it works with Google Workspace, Microsoft 365, or any custom-domain mailbox. Use port 465 for implicit TLS or 587 for STARTTLS.",
      "Built by TechZapp - https://techzapp.com/blueprints/hubspot-lead-autoresponder/"
    ]
  }
}
