

How to Sync Shopify Customers to HubSpot with Make
When a customer registers or places an order in Shopify, Make creates or updates their contact record in HubSpot with purchase history, tags, and contact details.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
E-commerce brands running targeted email campaigns in HubSpot who need purchase data from Shopify available in their CRM within minutes of a transaction.
Not ideal for
Stores with 5,000+ daily orders — at that volume, a dedicated integration like Shopify's native HubSpot app handles batching and rate limits more reliably.
Sync type
real-timeUse case type
syncReal-World Example
A 12-person DTC skincare brand uses this to push every new Shopify customer into HubSpot the moment they check out, including order value and product tags. Before this automation, their marketing team exported a CSV from Shopify every Monday and manually imported it — contacts were up to 7 days stale by the time a campaign launched. Now HubSpot reflects the customer's latest order within 90 seconds, and their post-purchase email sequence enrolls automatically.
What Will This Cost?
Drag the slider to your expected monthly volume.
Each platform counts differently — Zapier: 1 task per trigger. Make: 1 operation per module per record. n8n: 1 execution per run.





Prices shown for annual billing. Based on published pricing as of April 2026.
Estimated ROI
1000
min saved/mo
$583
labor value/mo
Free
no platform cost
Based on ~2 min manual effort per operation at $35/hr fully loaded labor cost.
Implementation
Import this workflow directly into Make
Copy the pre-built Make blueprint and paste it straight into Make. All modules, filters, and field mappings are already configured — you just need to connect your accounts.
Before You Start
Make sure you have everything ready.
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
email | ||
| First Name | firstname | |
| Last Name | lastname | |
| Shopify Customer ID | shopify_customer_id | |
| Accepts Marketing | hs_email_optout | |
7 optional fields▸ show
| Phone Number | phone |
| Last Order Value | last_order_value |
| Last Order Date | last_order_date |
| Total Orders Count | total_orders_count |
| City | city |
| Country | country |
| Customer Tags | shopify_customer_tags |
Step-by-Step Setup
make.com > Scenarios > Create a new scenario
Create a new Make scenario
Log into Make at make.com and click the blue 'Create a new scenario' button in the top right of your Scenarios dashboard. You'll land on the visual canvas with a single empty module in the center. This is where you'll chain together Shopify and HubSpot modules. Give the scenario a name immediately — click the default 'New scenario' text at the top left and type something like 'Shopify → HubSpot Customer Sync' so it's findable later.
- 1Log in at make.com
- 2Click 'Create a new scenario' in the top right
- 3Click the pencil icon next to 'New scenario' at the top left
- 4Type a descriptive name like 'Shopify → HubSpot Customer Sync'
- 5Click the large '+' circle in the canvas center to add the first module
Canvas > + Module > Shopify > Watch Orders
Add the Shopify 'Watch Orders' trigger
Click the empty module circle to open the app picker. Search for 'Shopify' and select it. From the trigger list, choose 'Watch Orders' — this fires in real time via webhook whenever a new order is placed, which also creates or identifies a customer record. This is the right trigger because it captures both new customer registrations that come with a first purchase and repeat buyers whose details may have changed.
- 1Click the empty '+' module on the canvas
- 2Type 'Shopify' in the search bar
- 3Select 'Shopify' from the results
- 4Click 'Watch Orders' from the trigger list
- 5Click 'Add' to create a new Shopify connection
Shopify Admin > Settings > Apps and sales channels > Develop apps > API credentials
Connect your Shopify store
In the connection modal, enter your Shopify store's subdomain (just the part before .myshopify.com), your API key, and your Admin API access token. You generate these in Shopify under Settings > Apps and sales channels > Develop apps. Make needs the 'read_orders' and 'read_customers' scopes at minimum. Name this connection something like 'Shopify - [Store Name]' so it's clear if you manage multiple stores.
- 1In Shopify Admin, go to Settings > Apps and sales channels
- 2Click 'Develop apps' then 'Create an app'
- 3Under 'Configuration', enable 'read_orders' and 'read_customers' API scopes
- 4Click 'Install app' and copy the Admin API access token
- 5Paste the store subdomain and access token into Make's connection modal
Watch Orders module > Settings panel
Configure the Watch Orders trigger settings
After connecting, Make asks which orders to watch. Set 'Order Status' to 'Any' so the trigger fires regardless of fulfillment state — you want the customer record the moment the order is placed, not after it ships. Set the 'Limit' field to 1 for real-time processing. Make will ask 'From which order do you want to start?' — choose 'From now on' unless you want to process a backlog, in which case pick a specific order ID.
- 1Set 'Order Status' to 'Any'
- 2Set 'Limit' to 1
- 3For the starting point selector, choose 'From now on'
- 4Click 'OK' to save the module configuration
Canvas > + after Watch Orders > Flow Control > Router
Add a Router to split new vs. existing customers
Click the '+' to the right of the Watch Orders module and add a 'Router' (found under Flow Control). The Router lets you send new customers down one path and returning customers down another — new customers need a HubSpot 'Create Contact' call, while existing ones need 'Update Contact'. Without this split, you'll create duplicate contacts every time a returning customer orders. You'll configure the filter conditions in the next step.
- 1Click the '+' arrow to the right of the Watch Orders module
- 2Click 'Flow Control' in the module picker
- 3Select 'Router'
- 4Confirm — two empty route branches appear on the canvas
Router Branch 1 > + Module > HubSpot CRM > Search for Contacts
Search HubSpot for an existing contact by email
On the first Router branch, add a HubSpot module: 'Search for Contacts'. Map the filter to search by the 'Email' property, using the value from Shopify's order output: {{1.customer.email}}. This query returns any existing HubSpot contact with that email. The result of this search determines which branch executes — if a contact is found, update it; if not, create it. Connect your HubSpot account using OAuth when prompted.
- 1Click the '+' on the first Router branch
- 2Search for 'HubSpot CRM' and select it
- 3Choose 'Search for Contacts'
- 4Connect HubSpot via OAuth — click 'Sign in with HubSpot' and authorize Make
- 5Set Filter Property to 'Email', Operator to 'Equal to', Value to
{{1.customer.email}}
Router > Click route connector wrench icon > Set filter condition
Add filters to each Router branch
Click the wrench icon on the Router connector between branch 1 and the next module to add a filter. For the 'Update' branch: set the condition to {{6.id}} (the HubSpot contact ID from the search) 'Exists'. For the 'Create' branch: set the condition to {{6.id}} 'Does not exist'. This ensures each order goes to exactly one path. Label each route clearly by clicking the route name — 'Existing Contact' and 'New Contact' keep the canvas readable.
- 1Click the wrench icon on the connector leaving the Router toward the update path
- 2Set Condition A to
{{6.id}}, Operator to 'Exists' - 3Click OK to save the filter
- 4Click the wrench icon on the second branch connector
- 5Set Condition A to
{{6.id}}, Operator to 'Does not exist', click OK
New Contact Branch > + Module > HubSpot CRM > Create a Contact
Map fields and create new HubSpot contacts
On the 'New Contact' branch (where {{6.id}} does not exist), add a HubSpot CRM 'Create a Contact' module. Map the Shopify order fields to HubSpot contact properties. At minimum, map email, first name, last name, and phone. For purchase data, map total order value to a custom HubSpot property (you'll need to create this in HubSpot under Properties first). See the Field Mapping section below for the full recommended list.
- 1Click '+' on the 'New Contact' branch
- 2Select 'HubSpot CRM' > 'Create a Contact'
- 3In the Email field, map
{{1.customer.email}} - 4Map First Name to
{{1.customer.first_name}}, Last Name to{{1.customer.last_name}} - 5Map Phone to
{{1.customer.phone}}, and Total Order Value to{{1.total_price}}
Existing Contact Branch > + Module > HubSpot CRM > Update a Contact
Map fields and update existing HubSpot contacts
On the 'Existing Contact' branch, add a HubSpot CRM 'Update a Contact' module. Set the Contact ID field to {{6.id}} — the ID returned by your earlier search. Map the same fields as the create step, plus any fields that change over time like phone number or marketing opt-in status. HubSpot's update call is a patch, so unmapped fields are left untouched — you don't need to re-send every property.
- 1Click '+' on the 'Existing Contact' branch
- 2Select 'HubSpot CRM' > 'Update a Contact'
- 3Set 'Contact ID' to
{{6.id}} - 4Map Email, Phone, and Last Order Value fields
- 5Map
{{1.total_price}}to your custom 'Last Order Value' HubSpot property
Canvas > Run once button (bottom toolbar) > Execution log
Test the full scenario end to end
Click 'Run once' in the bottom toolbar. Then place a test order in your Shopify store using a test customer email. Make's execution log will show each module lighting up green (success) or red (error). Click any module bubble in the log to inspect the exact data that passed through it. Check HubSpot manually to confirm the contact was created or updated with the correct field values. Run the test twice — once with a new email and once with an existing HubSpot contact email — to verify both Router branches work.
- 1Click 'Run once' in the bottom toolbar
- 2Place a test order in Shopify with a brand-new email address
- 3Watch the Make canvas — modules flash as they execute
- 4Click each module bubble to inspect input/output data
- 5Repeat with an email already in HubSpot to test the update branch
Canvas > Toggle switch (bottom left) > ON | Scenario Settings > Advanced
Activate the scenario and set scheduling
Once both test branches pass, click the toggle switch in the bottom left of the canvas from OFF to ON. Make will ask you to confirm activation. Because this scenario uses a webhook trigger (Watch Orders), it runs instantly on each Shopify order — you don't set a polling interval. However, you should set a scenario timeout under Settings > Advanced to 300 seconds so a slow HubSpot API response doesn't leave executions hanging. Also enable 'Auto-commit' in scenario settings so partial failures don't roll back successful modules.
- 1Click the OFF/ON toggle in the bottom left of the canvas
- 2Confirm activation in the dialog
- 3Click the gear icon (Scenario Settings) in the bottom toolbar
- 4Set 'Max number of cycles' to 1
- 5Set 'Sequential processing' to ON to prevent race conditions on rapid repeat orders
Paste this formula into Make's 'Phone' field mapping to handle Shopify's inconsistent phone data and normalize the accepts_marketing flag to HubSpot's expected boolean format. Use it directly in the field value box of the HubSpot Create or Update Contact module — no separate module needed.
JavaScript — Custom Function{{-- Phone fallback: use customer phone if present, otherwise use billing address phone --}}▸ Show code
{{-- Phone fallback: use customer phone if present, otherwise use billing address phone --}}
{{if(
and(1.customer.phone; length(trim(1.customer.phone)) > 0);... expand to see full code
{{-- Phone fallback: use customer phone if present, otherwise use billing address phone --}}
{{if(
and(1.customer.phone; length(trim(1.customer.phone)) > 0);
trim(1.customer.phone);
trim(1.billing_address.phone)
)}}
{{-- Email normalization for dedup search --}}
{{lower(trim(1.customer.email))}}
{{-- Convert Shopify total_price string to HubSpot number property --}}
{{toNumber(1.total_price)}}
{{-- Map accepts_marketing to HubSpot opt-out (inverted logic) --}}
{{-- HubSpot hs_email_optout = true means OPTED OUT --}}
{{if(1.customer.accepts_marketing; false; true)}}
{{-- Format Shopify ISO timestamp to HubSpot date format (YYYY-MM-DD) --}}
{{formatDate(1.created_at; "YYYY-MM-DD"; "America/New_York")}}
{{-- Build a readable customer tag string from Shopify array --}}
{{join(1.customer.tags; ", ")}}Going live
Production Checklist
Before you turn this on for real, confirm each item.
Troubleshooting
Common errors and how to fix them.
Frequently Asked Questions
Common questions about this workflow.
Analysis
Use Make for this if your team thinks visually, you're running a small-to-mid-size Shopify store (under 3,000 orders/month), and you need conditional logic — specifically the Router branch that separates new contact creation from updates. Make's canvas makes that deduplication logic easy to build and debug without writing code. The one scenario where you'd pick something else: if you're already on HubSpot Operations Hub Professional, their native Shopify integration handles this sync with zero setup and better error recovery than anything you'll build on Make.
Real cost math: each scenario run on Make costs 3–4 operations (Watch Orders = 1, Search Contacts = 1, Create or Update = 1, plus 1 for the Router). At 500 orders/month that's ~2,000 operations. Make's free tier allows 1,000 operations/month, so you'll exceed it. The Core plan at $10.59/month includes 10,000 operations — enough headroom for ~2,500 orders/month. Zapier's equivalent setup costs $19.99/month minimum (Starter plan) and counts each step as a task, so 500 orders × 3 steps = 1,500 tasks, which fits the Starter tier — but barely. Make is cheaper here by $9.40/month for mid-volume stores.
Honest competitor comparison: Zapier's Shopify 'New Order' trigger is faster to configure and fires more reliably (Shopify is a Zapier Premier Partner with optimized webhooks), but Zapier has no native Router — you'd need multi-step Zaps with filters and Pay-per-task pricing adds up fast. n8n handles this more elegantly in code with a single JavaScript node that does the search and upsert in one call, and it's free self-hosted, but someone on your team needs to maintain the instance. Power Automate has a Shopify connector in preview that's unreliable — Microsoft hasn't prioritized it. Pipedream lets you write the entire sync in 25 lines of JavaScript with native retry and built-in HTTP request logging, which is genuinely better for developers who want full control. Make wins for non-technical operators who need to maintain this themselves six months from now.
Three things you'll hit after go-live: First, Shopify's 'total_price' includes taxes and shipping — if your HubSpot contact property is meant to track product revenue only, you need to map subtotal_price instead, which most people miss on first setup. Second, Make scenarios occasionally miss a webhook if the scenario is in an error state when Shopify fires — Make does NOT retry missed webhooks by default. Enable the 'Incomplete executions' setting in scenario settings, which queues failed runs for manual replay. Third, HubSpot's Search for Contacts module has a bug where it returns an empty bundle (not null) when no contact is found — this means your {{6.id}} Does not exist filter may not evaluate as expected if you built the condition assuming a true null. Test this explicitly with an email you know isn't in HubSpot.
Ideas for what to build next
- →Sync HubSpot Contact Updates Back to Shopify — When a sales rep updates a phone number or address in HubSpot, that change currently doesn't reflect in Shopify. Build a reverse scenario using HubSpot's 'Watch Contacts' trigger to push updates back to Shopify's Customer API and keep both systems consistent.
- →Enroll Synced Contacts in HubSpot Post-Purchase Sequences — Add a HubSpot 'Add Contact to List' or 'Enroll in Workflow' module at the end of this scenario so new Shopify buyers immediately enter a post-purchase email sequence without any manual list management.
- →Add Slack Alerts for High-Value Orders — Extend this scenario with a filter after Watch Orders: if
total_priceexceeds a threshold (e.g. $500), route to a Slack 'Create a Message' module that posts the order details to your #sales channel so the team can follow up personally.
Related guides
How to Share Notion Meeting Notes to Slack with Pipedream
~15 min setup
How to Share Notion Meeting Notes to Slack with Power Automate
~15 min setup
How to Share Notion Meeting Notes to Slack with n8n
~20 min setup
How to Send Notion Meeting Notes to Slack with Zapier
~8 min setup
How to Share Notion Meeting Notes to Slack with Make
~12 min setup
How to Create Notion Tasks from Slack with Pipedream
~15 min setup