

How to Recover Abandoned Carts with HubSpot and Shopify in Power Automate
Triggers a HubSpot email sequence automatically when a Shopify customer abandons their cart, using a webhook to fire within minutes of cart abandonment.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.

Best for
Microsoft-stack e-commerce teams who already pay for Power Automate Premium and want abandoned cart emails inside HubSpot without a third-party tool
Not ideal for
Teams on Shopify's free or Basic plan who don't have a Premium Power Automate license — Make does this for free up to 1,000 ops/month
Sync type
real-timeUse case type
notificationReal-World Example
A 12-person direct-to-consumer brand sells $80–$200 skincare products on Shopify and tracks all customers in HubSpot. Before this flow, their marketing team manually exported abandoned cart reports from Shopify every Monday and bulk-imported them to HubSpot — meaning some customers received recovery emails four days late. After setting up this flow, HubSpot enrols abandoners into a three-email sequence within 15 minutes of cart abandonment, and the team recovered 11% of abandoned carts in the first month.
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 Power Automate
Copy the pre-built Power Automate blueprint and paste it straight into Power Automate. 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 | ||
| Customer Email | email | |
| First Name | firstname | |
| Abandoned Cart URL | abandoned_cart_url | |
| Cart Total Value | abandoned_cart_value | |
| Abandoned Cart Date | abandoned_cart_date | |
5 optional fields▸ show
| Last Name | lastname |
| Cart Item Count | abandoned_cart_item_count |
| Currency | hs_analytics_source |
| Phone Number | phone |
| Shopify Customer ID | shopify_customer_id |
Step-by-Step Setup
make.powerautomate.com > My flows > + New flow > Automated cloud flow
Create a new Automated Cloud Flow in Power Automate
Go to make.powerautomate.com and sign in. In the left sidebar click 'My flows', then click '+ New flow' at the top and select 'Automated cloud flow'. In the dialog box, name the flow something like 'Shopify Abandoned Cart → HubSpot Sequence'. For the trigger, type 'HTTP' in the search bar and select 'When a HTTP request is received' — this is the built-in Request connector. Click 'Create'.
- 1Click 'My flows' in the left sidebar
- 2Click '+ New flow' then select 'Automated cloud flow'
- 3Name the flow 'Shopify Abandoned Cart → HubSpot Sequence'
- 4Search for 'HTTP' in the trigger picker and select 'When a HTTP request is received'
- 5Click 'Create'
Flow designer > HTTP Request trigger card > Request Body JSON Schema
Configure the HTTP trigger and generate the webhook URL
Click the 'When a HTTP request is received' trigger card to expand it. In the 'Request Body JSON Schema' field, paste the JSON schema that matches Shopify's checkout/create webhook payload — this tells Power Automate how to parse the incoming data. After pasting the schema, click 'Save' at the top right. Power Automate will generate a unique HTTP POST URL in the trigger card. Copy this URL — you will paste it into Shopify in the next step.
- 1Click the trigger card to expand it
- 2Paste the Shopify checkout JSON schema into 'Request Body JSON Schema'
- 3Click 'Save' in the top toolbar
- 4Copy the generated HTTP POST URL from the trigger card
Shopify Admin > Settings > Notifications > Webhooks > Create webhook
Register the webhook in Shopify
In Shopify Admin, go to Settings > Notifications > Webhooks (scroll to the bottom of the Notifications page). Click 'Create webhook'. Set the Event to 'Checkout creation' and the Format to 'JSON'. Paste the Power Automate HTTP POST URL you copied in Step 2 into the URL field. Set the Webhook API version to the latest stable version (currently 2024-01). Click 'Save'. Shopify will send a verification ping — Power Automate will receive it automatically.
- 1In Shopify Admin, click 'Settings' then 'Notifications'
- 2Scroll to the bottom and click 'Create webhook'
- 3Set Event to 'Checkout creation' and Format to 'JSON'
- 4Paste your Power Automate URL into the URL field
- 5Click 'Save'
Flow designer > + New step > Data Operation > Parse JSON
Add a Parse JSON action to extract cart fields
Back in Power Automate, click '+ New step' below the trigger. Search for 'Parse JSON' and select the 'Parse JSON' action from the Data Operation connector. In the Content field, click inside the box and select 'Body' from the dynamic content panel — this is the raw payload from Shopify. In the Schema field, paste the same Shopify checkout JSON schema you used in the trigger. This step maps the nested Shopify payload into usable dynamic content fields like customer email, first name, cart total, and line items.
- 1Click '+ New step'
- 2Search for 'Parse JSON' and select it under Data Operation
- 3In the Content field, select 'Body' from the dynamic content panel
- 4Paste the Shopify checkout JSON schema into the Schema field
Flow designer > + New step > Control > Condition
Add a Condition to filter out completed purchases
Click '+ New step' and search for 'Condition'. Select the 'Condition' control action. In the left value box, pick 'completed_at' from the Parse JSON dynamic content. Set the operator to 'is equal to'. In the right value box, type null (without quotes). This checks whether the checkout was abandoned (completed_at is null) versus purchased (completed_at has a timestamp). All subsequent HubSpot actions go inside the 'If yes' branch.
- 1Click '+ New step' and search for 'Condition'
- 2Select 'Condition' under Control
- 3In the left value, pick 'completed_at' from dynamic content
- 4Set the operator to 'is equal to'
- 5Type null in the right value box
Flow designer > If yes branch > Add an action > HubSpot > Search for a contact
Search for or create a HubSpot contact
Inside the 'If yes' branch, click 'Add an action'. Search for 'HubSpot' and select 'Search for a contact' (or 'Get a contact by its email' depending on the connector version). In the Email field, insert the 'email' dynamic content value from the Parse JSON step. This step checks whether the abandoning customer already exists in HubSpot. If no matching contact is found, add a second action immediately after: 'Create a contact', and map the email, first name, and last name fields from the Shopify payload.
- 1Click 'Add an action' inside the 'If yes' branch
- 2Search for 'HubSpot' and select 'Search for a contact'
- 3Set the Email field to the 'email' dynamic content from Parse JSON
- 4Add another action 'Create a contact' for cases where no match is found
- 5Map first_name and last_name from billing_address in the Create action
Flow designer > If yes branch > Add an action > HubSpot > Update a contact
Update HubSpot contact properties with cart data
Add an 'Update a contact' action from the HubSpot connector. Set the Contact ID to the ID returned from the search or create step. Map the following custom HubSpot contact properties: abandoned_cart_url (from Shopify's abandoned_checkout_url field), abandoned_cart_value (from total_price), and abandoned_cart_date (from created_at). These properties must already exist in HubSpot as custom contact properties — if they don't, create them first under Settings > Properties in HubSpot. These values will be used for personalisation tokens in your email sequence.
- 1Add a 'Update a contact' action from HubSpot
- 2Set Contact ID to the ID from the previous search/create step
- 3Map 'abandoned_cart_url' to the Shopify 'abandoned_checkout_url' field
- 4Map 'abandoned_cart_value' to the Shopify 'total_price' field
- 5Map 'abandoned_cart_date' to the Shopify 'created_at' field
Flow designer > If yes branch > Add an action > HubSpot > Enroll a contact in a workflow
Enrol the contact in a HubSpot email sequence
Add a new action and search for 'HubSpot'. Look for 'Enroll a contact in a workflow' — this maps to HubSpot's marketing automation workflows, not Sequences (which require a Sales Hub seat and do not have a direct Power Automate action). Select the target HubSpot workflow ID from the dropdown — this should be your pre-built abandoned cart recovery workflow inside HubSpot that contains your three-email drip. Set the Contact ID to the ID resolved in Step 6.
- 1Add an action and search for 'HubSpot'
- 2Select 'Enroll a contact in a workflow'
- 3Pick your abandoned cart recovery HubSpot workflow from the Workflow ID dropdown
- 4Set Contact ID to the ID from Step 6
Flow designer > If yes branch > Add an action > Schedule > Delay
Add a delay to avoid emailing customers who complete checkout
Some customers abandon the checkout page temporarily and come back within 30–60 minutes to complete the purchase. To avoid emailing paying customers, add a 'Delay' action from the Schedule connector before the HubSpot enrolment step. Set it to 1 hour. Then add a second 'Get an order' action from the Shopify connector to check whether a completed order exists for this email in the past hour. Only proceed to enrolment if no order is found.
- 1Click 'Add an action' before the HubSpot enrolment step
- 2Search for 'Delay' and select it from the Schedule connector
- 3Set the delay to 1 hour
- 4Add a Shopify 'Search orders' action after the delay
- 5Add a condition: only enrol in HubSpot if no completed order is found for this email
make.powerautomate.com > My flows > [Flow name] > Run history
Test the end-to-end flow with a real Shopify checkout
In Shopify Admin, go to your store and add a product to cart as a test customer. Proceed to checkout, enter an email address you control, and stop — do not complete the purchase. Wait 2 minutes, then in Power Automate go to My flows, click your flow name, and scroll to the 'Run history' panel at the bottom. You should see a new run triggered. Click it to see each action's inputs and outputs. Verify the contact was created or updated in HubSpot and appeared in the workflow's enrolled list.
- 1Open your Shopify store and add a product to cart
- 2Go to checkout and enter a test email — stop before payment
- 3Wait 2 minutes then go to My flows in Power Automate
- 4Click your flow name and scroll to 'Run history'
- 5Click the latest run and verify each step shows a green checkmark
make.powerautomate.com > My flows > [Flow name] > Turn on
Enable the flow and monitor for the first 48 hours
Click 'Turn on' at the top of your flow detail page if it is not already active. For the first 48 hours, check Run history once or twice a day. Filter runs by 'Failed' to catch any errors early. Set up a failure notification: go to the flow's three-dot menu > 'Edit', add an action at the very end of the 'If no' branch and the main flow scope — use 'Send an email (V2)' or Teams message to alert your team if any run fails. This catches issues like HubSpot token expiry or Shopify schema changes before they go unnoticed.
- 1Click 'Turn on' on the flow detail page
- 2Go to Run history and filter by 'Failed'
- 3Edit the flow and add an error notification action for failures
- 4Set the notification to email or Microsoft Teams
Paste this expression into a Power Automate 'Compose' action placed between Parse JSON and the HubSpot Update action. It builds a formatted cart summary string (e.g., '3 items — $124.00 USD') and type-casts total_price from string to float, preventing the HubSpot 400 error described in troubleshooting. Reference the Compose output as 'cart_summary' in your HubSpot update action using outputs('Compose_Cart_Summary').
JavaScript — Code Step// Add a 'Compose' action named 'Compose_Cart_Summary' between Parse JSON and HubSpot Update▸ Show code
// Add a 'Compose' action named 'Compose_Cart_Summary' between Parse JSON and HubSpot Update // Expression to build a cart summary and cast price correctly: // In the 'Compose' action Inputs field (Expression mode), paste:
... expand to see full code
// Add a 'Compose' action named 'Compose_Cart_Summary' between Parse JSON and HubSpot Update
// Expression to build a cart summary and cast price correctly:
// In the 'Compose' action Inputs field (Expression mode), paste:
concat(
string(body('Parse_JSON')?['line_items']?['length']),
' item(s) — ',
string(float(body('Parse_JSON')?['total_price'])),
' ',
toUpper(body('Parse_JSON')?['currency'])
)
// Output example: '3 item(s) — 124.0 USD'
// In a second 'Compose' action named 'Compose_Cart_Price_Float':
// Cast total_price string to float for HubSpot number property:
float(body('Parse_JSON')?['total_price'])
// Use outputs('Compose_Cart_Price_Float') in the HubSpot Update contact
// 'abandoned_cart_value' field instead of the raw dynamic content token.
// This prevents HubSpot's 400 type mismatch error on number properties.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 Power Automate for this if your organisation already pays for Microsoft 365 E3/E5 or Dynamics 365 — because Power Automate Premium is likely already included in your licensing at no extra per-flow cost. It also fits well if your team uses Teams heavily, since failure notifications and alerts slot naturally into existing Teams channels. The one scenario where you should pick something else: if you have no existing Microsoft licensing and would be buying Power Automate Premium ($15/user/month) purely for this flow. At that point, Make does the same job for free under 1,000 operations per month.
The cost math is straightforward. This flow uses roughly 8 actions per run: HTTP trigger, Parse JSON, Condition, Delay, Shopify order check, HubSpot search, HubSpot update, HubSpot enrol. Power Automate counts each action as one run against your Power Platform request limits. On a per-user Premium plan ($15/month), you get 40,000 Power Platform requests per day — far more than any Shopify store will generate in abandoned carts. The real cost ceiling is the Premium license itself: $15/user/month. Make handles the same flow for $0 on the free tier up to 1,000 operations/month, or $9/month on the Core plan for up to 10,000 ops. If you are buying Power Automate purely for this use case, Make is $6–$15/month cheaper.
Make's standout advantage here is its visual scenario builder with a dedicated Shopify 'Watch abandoned checkouts' module — no webhook configuration required, no JSON schema to write, and it polls every 15 minutes. Zapier has a 'New Abandoned Cart' Shopify trigger that is even simpler, but at 50+ tasks/month you hit paid tiers fast and Zapier's HubSpot workflow enrolment action has historically been unreliable — support threads from 2023 show it silently failing on re-enrolment. n8n lets you self-host the entire flow with no per-run cost, and its Shopify webhook node plus HubSpot node are both mature. Pipedream's free tier covers 10,000 workflow executions per month, which beats everything else on raw cost for moderate volume. Power Automate wins when your team is already in the Microsoft ecosystem, when you need the flow to interact with SharePoint, Teams, or Dynamics data alongside HubSpot, or when your IT department requires data to stay within Azure regions for compliance reasons.
Three things you will hit after setup. First, Shopify's abandoned_checkout_url expires after 30 days — if your HubSpot workflow sends a fourth recovery email on day 31, the link is dead. Cap your workflow at 7 days maximum. Second, Power Automate's dynamic content from the Parse JSON step stops showing nested array items (like individual line item names) unless your JSON schema explicitly declares them — most tutorials skip this and then wonder why product names are blank in emails. Third, if your HubSpot workflow has a 're-enrollment' suppression setting that checks 'contact is currently in workflow', Power Automate's enrolment call will silently succeed (200 OK) but HubSpot will not actually re-enrol the contact. You will see successful Power Automate runs and no actual emails sent. Always test re-enrolment scenarios explicitly before launch.
Ideas for what to build next
- →Add SMS recovery via HubSpot's SMS feature — If a contact's recovery email goes unopened after 24 hours, trigger an additional HubSpot workflow branch that sends an SMS reminder using the phone number captured at checkout. Add a second Power Automate condition that checks email open status via HubSpot's API before firing the SMS step.
- →Sync Shopify order completions back to HubSpot to suppress recovery emails — Create a second Power Automate flow triggered by Shopify's 'Order paid' webhook that unenrols the contact from the HubSpot abandoned cart workflow immediately. Without this, customers who purchase on a different device or browser session may still receive recovery emails after buying.
- →Log abandoned cart events as HubSpot deals for sales team visibility — For high-value carts (e.g., over $300), extend this flow to also create a HubSpot deal in a 'High-Value Abandoned Cart' pipeline stage. This alerts your sales team to personally follow up rather than relying solely on automated emails.
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