Intermediate~15 min setupCRM & E-commerceVerified April 2026
HubSpot logo
Shopify logo

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-time

Use case type

notification

Real-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.

/mo
505005K50K

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

Skip the setup

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.

Power Automate Premium license (per-user or per-flow) — the HTTP Request trigger is a Premium connector and is not available on the free plan
Shopify Admin access with permission to manage Webhooks under Settings > Notifications
HubSpot Marketing Hub account with workflow creation permissions and a pre-built abandoned cart recovery workflow ready to enrol contacts into
Custom HubSpot contact properties created: abandoned_cart_url (single-line text), abandoned_cart_value (number), abandoned_cart_date (date picker)
HubSpot OAuth connection established in Power Automate with scopes: contacts.read, contacts.write, automation.workflows.read, automation.workflows.write

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Customer Emailemail
First Namefirstname
Abandoned Cart URLabandoned_cart_url
Cart Total Valueabandoned_cart_value
Abandoned Cart Dateabandoned_cart_date
5 optional fields▸ show
Last Namelastname
Cart Item Countabandoned_cart_item_count
Currencyhs_analytics_source
Phone Numberphone
Shopify Customer IDshopify_customer_id

Step-by-Step Setup

1

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'.

  1. 1Click 'My flows' in the left sidebar
  2. 2Click '+ New flow' then select 'Automated cloud flow'
  3. 3Name the flow 'Shopify Abandoned Cart → HubSpot Sequence'
  4. 4Search for 'HTTP' in the trigger picker and select 'When a HTTP request is received'
  5. 5Click 'Create'
What you should see: The flow designer opens with the 'When a HTTP request is received' trigger card at the top. The HTTP POST URL field is blank — it will generate after you save the flow for the first time.
Common mistake — Do not select 'Manually trigger a flow' or 'Scheduled cloud flow' by mistake. The webhook trigger ('When a HTTP request is received') is the only one that fires in real time from Shopify.
2

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.

  1. 1Click the trigger card to expand it
  2. 2Paste the Shopify checkout JSON schema into 'Request Body JSON Schema'
  3. 3Click 'Save' in the top toolbar
  4. 4Copy the generated HTTP POST URL from the trigger card
What you should see: A long HTTPS URL appears in the 'HTTP POST URL' field starting with 'https://prod-xx.westus.logic.azure.com'. This is your webhook endpoint.
Common mistake — The URL only generates after the first save. If you skip saving, the field stays blank and Shopify will have nothing to send data to.
Power Automate
+
click +
search apps
HubSpot
HU
HubSpot
Configure the HTTP trigger a…
HubSpot
HU
module added
3

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.

  1. 1In Shopify Admin, click 'Settings' then 'Notifications'
  2. 2Scroll to the bottom and click 'Create webhook'
  3. 3Set Event to 'Checkout creation' and Format to 'JSON'
  4. 4Paste your Power Automate URL into the URL field
  5. 5Click 'Save'
What you should see: Shopify shows 'Webhook saved' and the new webhook appears in the list with a green status indicator. You can click 'Send test notification' to fire a sample payload.
Common mistake — Shopify's 'Checkout creation' fires as soon as a customer reaches checkout — even if they complete the purchase. You must add a conditional check in Power Automate later (Step 5) to filter out completed orders, or you will trigger recovery emails for paying customers.
4

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.

  1. 1Click '+ New step'
  2. 2Search for 'Parse JSON' and select it under Data Operation
  3. 3In the Content field, select 'Body' from the dynamic content panel
  4. 4Paste the Shopify checkout JSON schema into the Schema field
What you should see: The Parse JSON card shows a green checkmark on schema validation. When you click into any subsequent action, the dynamic content panel now lists parsed fields like 'email', 'total_price', 'line_items', 'billing_address first_name'.
Common mistake — If your schema does not include the 'line_items' array explicitly, Power Automate will not expose individual product names or prices as dynamic content — only the raw JSON string. Make sure your schema has line_items defined as an array of objects.
HubSpot fields
firstname
lastname
email
company
hs_lead_status
available as variables:
1.props.firstname
1.props.lastname
1.props.email
1.props.company
1.props.hs_lead_status
5

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.

  1. 1Click '+ New step' and search for 'Condition'
  2. 2Select 'Condition' under Control
  3. 3In the left value, pick 'completed_at' from dynamic content
  4. 4Set the operator to 'is equal to'
  5. 5Type null in the right value box
What you should see: The condition card shows two branches: 'If yes' and 'If no'. All actions inside 'If yes' will only run when the cart has not been completed — i.e., it is genuinely abandoned.
Common mistake — Filters are the most common place setups break. Double-check the field name and value exactly match what your app sends — a single capital letter difference will block everything.
HubSpot
HU
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Shopify
SH
notified
6

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.

  1. 1Click 'Add an action' inside the 'If yes' branch
  2. 2Search for 'HubSpot' and select 'Search for a contact'
  3. 3Set the Email field to the 'email' dynamic content from Parse JSON
  4. 4Add another action 'Create a contact' for cases where no match is found
  5. 5Map first_name and last_name from billing_address in the Create action
What you should see: The HubSpot connector prompts you to sign in or pick an existing Connection. After connecting, the action card shows the Email field populated with the Shopify email token. You should see 'Connected to HubSpot' with your portal name displayed.
Common mistake — The HubSpot connector in Power Automate authenticates via OAuth and ties to a specific HubSpot portal. If your team has multiple portals (e.g., sandbox and production), confirm you connected to the production portal before building further steps.
7

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.

  1. 1Add a 'Update a contact' action from HubSpot
  2. 2Set Contact ID to the ID from the previous search/create step
  3. 3Map 'abandoned_cart_url' to the Shopify 'abandoned_checkout_url' field
  4. 4Map 'abandoned_cart_value' to the Shopify 'total_price' field
  5. 5Map 'abandoned_cart_date' to the Shopify 'created_at' field
What you should see: The Update action card shows each mapped field with a dynamic content token. When you run a test, these values appear on the contact record in HubSpot under the custom properties section.
Common mistake — HubSpot stores monetary values as numbers, not strings. If Shopify sends total_price as '85.00' (a string), HubSpot will reject the update with a type mismatch error. Use a Power Automate expression — float(body('Parse_JSON')?['total_price']) — to cast it before mapping.
8

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.

  1. 1Add an action and search for 'HubSpot'
  2. 2Select 'Enroll a contact in a workflow'
  3. 3Pick your abandoned cart recovery HubSpot workflow from the Workflow ID dropdown
  4. 4Set Contact ID to the ID from Step 6
What you should see: The action card shows your HubSpot workflow name in the Workflow ID field. On test run, the contact appears in the HubSpot workflow's enrolled contacts list within 1–2 minutes.
Common mistake — HubSpot's 'Sequences' (Sales Hub) and 'Workflows' (Marketing Hub) are different products. The Power Automate HubSpot connector only supports workflow enrolment — not Sequences enrolment. If your team is using Sequences, you need the HubSpot API via an HTTP action instead.
9

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.

  1. 1Click 'Add an action' before the HubSpot enrolment step
  2. 2Search for 'Delay' and select it from the Schedule connector
  3. 3Set the delay to 1 hour
  4. 4Add a Shopify 'Search orders' action after the delay
  5. 5Add a condition: only enrol in HubSpot if no completed order is found for this email
What you should see: The flow canvas now shows: Trigger → Parse JSON → Condition (abandoned?) → Delay 1hr → Check for completed order → Enrol in HubSpot workflow. The delay will appear in the run history with a clock icon during the wait period.
Common mistake — Power Automate's free and per-user plans pause delayed flows in storage — this is fine. But if your Power Automate environment has low storage quota (under 2 GB), large volumes of paused flow runs can hit the limit. Check storage under Admin Center > Environments > your environment.
10

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.

  1. 1Open your Shopify store and add a product to cart
  2. 2Go to checkout and enter a test email — stop before payment
  3. 3Wait 2 minutes then go to My flows in Power Automate
  4. 4Click your flow name and scroll to 'Run history'
  5. 5Click the latest run and verify each step shows a green checkmark
What you should see: Run history shows a successful run with green checkmarks on all steps. In HubSpot, the test contact exists with abandoned_cart_url, abandoned_cart_value, and abandoned_cart_date populated. The contact appears in the workflow's enrolled tab.
Power Automate
▶ Test flow
executed
HubSpot
Shopify
Shopify
🔔 notification
received
11

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.

  1. 1Click 'Turn on' on the flow detail page
  2. 2Go to Run history and filter by 'Failed'
  3. 3Edit the flow and add an error notification action for failures
  4. 4Set the notification to email or Microsoft Teams
What you should see: The flow status shows 'On' with a green indicator. Run history populates with real customer events within a few hours of enabling, depending on your store's traffic.

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

VerdictWhy n8n for this workflow

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.

Cost

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.

Tradeoffs

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 featureIf 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 emailsCreate 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 visibilityFor 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

Was this guide helpful?
HubSpot + Shopify overviewPower Automate profile →