HomeShopify & E-commerceSync Shopify Customers to HubSpot with…

Sync Shopify Customers to HubSpot with n8n (Free, Real-Time)

Sync Shopify Customers to HubSpot with n8n (Free, Real-Time)









This guide shows you how to sync Shopify customers to HubSpot with n8n in real time, so every new or updated shopper lands in your CRM within seconds. Two Shopify webhooks catch customer events, a Filter drops records with no email, an Edit Fields node maps the data, and the HubSpot node upserts a contact by email. No duplicates, no paid sync app, and no manual CSV exports ever again.

Prefer to skip the build? Grab the ready-made template at the bottom of this guide and be syncing in under ten minutes.

What it does

Your customer list lives in Shopify, but your sales follow-up, lists, and reporting live in HubSpot. Keeping the two in sync by hand means exporting a CSV every week, deduping it, and re-importing. Customers who bought yesterday sit invisible in your CRM until you get around to it.

This workflow closes that gap. The moment a shopper creates an account or updates their details in Shopify, n8n receives the event, cleans the data, and writes a HubSpot contact. The same run handles both first-time customers and edits to existing ones, so your CRM always mirrors the store.

Concretely, once it is live:

  1. A customer signs up or is created at checkout in Shopify.
  2. n8n receives the customers/create (or customers/update) webhook instantly.
  3. The record is checked for a valid email and mapped to HubSpot fields.
  4. HubSpot creates a new contact, or updates the existing one that shares that email.

You get a HubSpot contact database that stays current on its own, complete with each shopper’s order count and lifetime spend carried over as custom properties.

Why it beats the default

Shopify and HubSpot both sell you a way to bridge them, and both have real drawbacks.

Approach Cost The catch
Manual CSV export/import Free Stale within a day, dedupe headaches, easy to forget
Paid connector app $15 to $50+ per month Recurring fee, rigid field mapping, another vendor to trust
HubSpot native Shopify sync Paid tiers Locks the useful settings behind higher plans, limited field control
This n8n workflow Free (self-hosted) You own the mapping and the logic end to end

With n8n you decide exactly which Shopify fields become which HubSpot properties, you add or remove custom fields whenever you like, and you pay nothing beyond the server you already run. When Shopify changes a payload or you want to enrich the contact before it lands, you edit one node instead of filing a support ticket. This is the same building-block approach behind our wider library of n8n Shopify automation guides.

What you need

  • A running n8n instance (Cloud or self-hosted, version 1.0 or newer).
  • A Shopify store and a custom app created through the 2026 Dev Dashboard. If you have not connected Shopify to n8n yet, follow connect Shopify to n8n (2026 method) first; the trigger needs the read_customers scope.
  • A free HubSpot account with a Private App token (we cover this below).
  • About 30 minutes if you build from scratch, or under 10 with the template.

Node-by-node list

Five nodes, one straight line with two entry points:

  [Shopify Trigger: customers/create] --.
                                         >--[Filter: email exists]--[Edit Fields: map]--[HubSpot: create/update contact]
  [Shopify Trigger: customers/update] --'
# Node Type Job
1 New Customer n8n-nodes-base.shopifyTrigger Fires on customers/create
2 Updated Customer n8n-nodes-base.shopifyTrigger Fires on customers/update
3 Has Email? n8n-nodes-base.filter Continues only if email is set
4 Map to HubSpot n8n-nodes-base.set Shapes the payload into HubSpot properties
5 Upsert Contact n8n-nodes-base.hubspot Create or Update a contact by email

Step-by-step build

1 New Customer (Shopify Trigger)

Add a Shopify Trigger node. Select your Shopify credential (set up via the 2026 Dev Dashboard method), then set Topic to Customer Created. n8n registers the webhook with Shopify automatically the first time the workflow is active. A new sign-up now delivers a payload like this:

{
  "id": 8213004821,
  "email": "james.carter@gmail.com",
  "first_name": "James",
  "last_name": "Carter",
  "phone": "+1 555 234 7890",
  "orders_count": 0,
  "total_spent": "0.00",
  "tags": "",
  "default_address": {
    "city": "Austin",
    "province_code": "TX",
    "country": "United States"
  }
}
💡

Tip: Use n8n’s Listen for event button and create a test customer in Shopify to capture a real payload. Everything downstream can then be mapped by clicking fields instead of typing expressions.

2 Updated Customer (Shopify Trigger)

Add a second Shopify Trigger with the same credential but Topic set to Customer Updated. This catches address changes, new orders raising the order count, and marketing-consent edits. Both triggers are entry points and both connect forward to the same Filter node, so you maintain the mapping in one place.

📌

Do not chain the two triggers together. Each is an independent start of the flow; wire both of their outputs into the Filter node.

3 Has Email? (Filter)

Add a Filter node so only records with an email reach HubSpot. Set one condition:

  • Value 1: ={{ $json.email }}
  • Operation: is not empty

Shopify allows phone-only customers, and HubSpot keys contacts on email, so this guard stops the workflow from failing on records it cannot upsert.

4 Map to HubSpot (Edit Fields)

Add an Edit Fields node (also called Set). Keep only set fields listed below off, and add one assignment per property so the payload matches HubSpot’s field names:

Name Type Value
email String ={{ $json.email }}
firstname String ={{ $json.first_name }}
lastname String ={{ $json.last_name }}
phone String ={{ $json.phone }}
city String ={{ $json.default_address?.city }}
state String ={{ $json.default_address?.province_code }}
shopify_customer_id String ={{ $json.id }}
shopify_orders_count Number ={{ $json.orders_count }}
shopify_total_spent Number ={{ $json.total_spent }}

The first four map to HubSpot’s built-in contact properties. The last three are custom properties you create once inside HubSpot under Settings → Properties → Create property, on the Contact object, named exactly as above.

📌

Create shopify_customer_id, shopify_orders_count, and shopify_total_spent in HubSpot before your first run. Sending a value for a property that does not exist returns a 400 error.

5 Upsert Contact (HubSpot)

Add the HubSpot node and configure it:

  1. Authentication: App Token, using the Private App token from your HubSpot account.
  2. Resource: Contact.
  3. Operation: Create or Update.
  4. Email: ={{ $json.email }} — this is the match key.
  5. Under Additional Fields, add First Name, Last Name, Phone Number, City, State, and each custom property, pulling from the mapped fields (for example First Name = ={{ $json.firstname }}).

Because the operation is Create or Update, HubSpot matches on the email. A brand-new email becomes a fresh contact; a known email updates the record in place. That single choice is what keeps your CRM clean.

💡

Tip: Turn on Save Execution Data for this workflow so you can see exactly what was sent to HubSpot if a contact ever looks wrong.

Save the workflow, toggle it Active, and you are live. Create a test customer in Shopify and watch the contact appear in HubSpot seconds later.

Common mistakes

  • Skipping the custom properties. Sending shopify_total_spent before it exists in HubSpot throws a 400. Create all three custom properties first.
  • Chaining the two triggers. Both Shopify Triggers are separate entry points. Wire each one into the Filter; never connect one trigger’s output into the other.
  • Wrong Shopify scope. Without read_customers the webhooks never register. Set the scope when you create the app.
  • No email guard. Remove the Filter and phone-only customers will fail the HubSpot step and clutter your execution log with errors.
  • Expecting deduplication elsewhere. The safety against duplicates comes entirely from the Create or Update operation matching on email. Do not switch it to plain Create.

Cost at realistic volume

Take a store adding 500 new or updated customers a month.

Component Usage Cost
Shopify webhooks 500 events Free (built in)
n8n (self-hosted) 500 executions Free
HubSpot free CRM 500 contact upserts Free (up to 1M contacts)
Total $0 / month

Even at 5,000 customer events a month you stay comfortably inside HubSpot’s free API allowance (100 requests per 10 seconds) because Shopify delivers webhooks in a steady trickle, not a burst. The only real cost is the server you already run n8n on.

Get the Shopify to HubSpot Sync template

The guide above is free to follow. If you would rather skip the build, download the ready-to-import workflow, then just add your credentials. Prefer it installed and tuned for you? See our done-for-you services.

Download the template ($12) →

Instant download · Works on n8n Cloud and self-hosted

FAQ

Does this create duplicate contacts in HubSpot?

No. The HubSpot node uses the Create or Update operation, which matches on the email address. If a contact with that email already exists, HubSpot updates it instead of adding a new record, so re-syncing the same customer is always safe.

What if a Shopify customer has no email address?

The Filter node drops those records before they reach HubSpot. HubSpot identifies contacts by email, so a phone-only Shopify customer cannot be upserted. Filtering them out keeps the workflow from erroring on records it cannot process.

Can I sync historical Shopify customers, not just new ones?

Yes. Add a one-time branch with a Schedule Trigger plus the Shopify Get All Customers operation, loop the results through the same Filter, Edit Fields, and HubSpot nodes, then disable that branch once the backfill finishes.

Do I need a paid HubSpot plan for this?

No. The free HubSpot CRM stores up to one million contacts and its API supports contact create and update. You only need a paid tier if you later add marketing email or workflow automations inside HubSpot itself, which this n8n workflow does not require.

Which Shopify API scope does the trigger need?

The connection needs read_customers so the customers/create and customers/update webhooks can fire and return the full customer payload. Set this scope when you create the app in the Shopify Dev Dashboard, following the 2026 connection guide linked above.

Related guides

n8n
Shopify
HubSpot
CRM
automation