All systems operational200+ sites we watch overReply in under 2h+54 9 11 7820-8554
← Blog

Shopify CRM integration: how to hire the right team

For e-commerce and operations managers: how to scope a Shopify CRM integration, choose connector, n8n or custom code, map data, handle failures and hire a team.

werun.dev19 min read
Get a summary withChatGPTClaudeGoogle AI Mode
Abstract network of linked nodes illustrating a Shopify CRM integration between a storefront and a CRM

A Shopify CRM integration looks like a small job. Orders flow into HubSpot or Salesforce, customers become contacts and sales stops copying data between tabs. In practice it is a contract between two systems that disagree about what a customer is.

Most advice on how to hire for it says the same thing: scope the work, check references, compare quotes. That is right and incomplete. It skips what decides whether the sync survives its first bad week: the data mapping, failure handling, the cost over twelve months and who owns the sync once the agency leaves.

This is a buyer's playbook for e-commerce and operations managers. It shows how to scope the job, choose between a connector, n8n and custom code, agree a mapping, write a contract and plan a timeline. Costs appear as shapes, and any worked numbers are marked illustrative.

Key takeaways

  • Scope the objects, direction, source of truth and freshness before you ask anyone for a quote.
  • Choose a connector, n8n or custom code by logic complexity and order volume, not by price alone.
  • Agree the data mapping table first, including refunds and marketing consent.
  • Demand idempotent writes, retries, a dead-letter queue and nightly reconciliation from any team you hire.
  • Get ownership of the accounts, the code and the alert channel in writing before work starts.

Shopify CRM integration: what the scope covers

Before you compare vendors, write down what the integration must do. A team can only quote what you can describe, and a vague brief produces a vague fixed price. Scope for a Shopify CRM integration comes down to four decisions: which systems, which objects, which direction and how fresh the data must be.

Two islands, a storefront and a dashboard, linked by a few glowing bridges carrying data cubes
Scope decides which bridges you build and what crosses them

Skip any of them and every proposal hides a different set of assumptions. You end up comparing prices for different jobs.

The objects that actually sync

Most stores need four objects: customers, orders, refunds and marketing consent. Larger setups add products and inventory (usually owned by an ERP), subscriptions, B2B companies and support tickets. Each object is its own mapping, its own test cycle and its own way to fail.

Name the CRM and every other app in the same document. Count objects and systems, not tools: two systems with four objects each is eight mappings.

One-way, two-way and source of truth

One-way means Shopify writes and the CRM reads. Two-way means both systems can change the same field, and that is where budgets grow, because every shared field needs a conflict rule.

Pick a source of truth per field, not per system. Shopify owns order totals, payment status and the shipping address at purchase. The CRM owns lifecycle stage, account owner, sales notes and deal stage.

Default to one-way for commerce data and write back only what the store needs, such as a segment or a tag. Not two-way everywhere. One-way with two precise write-backs.

How fresh the data needs to be

Real time sounds good and costs more. A sales rep calling after an abandoned checkout needs minutes. A finance report needs a daily close. Write the targets as numbers in the brief, for example: orders reach the CRM within five minutes, customer updates within an hour, totals reconcile every night.

Shopify gives you two tools for this: webhooks for live events and the Admin GraphQL API for reads, backfills and bulk operations. Both are rate limited, which is the first reason a sync needs a queue.

Connector, n8n or custom code: when each wins

There are three ways to build this integration, and each moves cost and risk to a different place. The right pick depends on the logic you need and your order volume, not on which tool is fashionable.

Prebuilt connector: fast, limited

A prebuilt connector is an app from the Shopify App Store or the CRM marketplace. You pay a subscription, often tiered by volume or features, and you configure rather than build. It wins when your needs match its fixed model: standard objects, one direction, no custom rules.

It loses on the first custom field, the first conditional rule or the second system. You usually cannot change how it retries, and you often cannot see why a record failed.

Middleware with n8n: control without a full build

n8n is a workflow tool you can self-host or run in the cloud. A workflow receives the Shopify webhook, transforms the payload, calls the CRM API and handles errors on a canvas you can read. Cost is hosting or a plan plus build hours. Our comparison of n8n, Zapier and Make covers pricing mechanics and limits.

It wins for mid-size stores with two or three systems and custom rules: retries, branching and error workflows are built in. It loses at very high volume, or when the logic needs software structure such as tests and versioned releases. The n8n docs describe a queue mode for scaling, but at that point a custom app deserves a quote.

Custom app: when the logic is yours

A custom app is code you own: a Next.js or Node service with a queue and a database. It suits high volume, complex pricing, B2B hierarchies and anything that needs tests and CI. Cost is the highest build plus a maintenance commitment, because Shopify releases API versions on a schedule and retires old ones.

Cost shape of each option over 12 months

Prices change, so we describe the shape of each option first and then run an illustrative example. Fit and control come before money.

Option A

Prebuilt connector

  • Fit: standard objects, one direction
  • Cost: monthly subscription
  • Control: configuration only
  • Failures: limited visibility

Our pick for most mid-size stores

n8n middleware

  • Fit: two or three systems, custom rules
  • Cost: build hours plus hosting or a plan
  • Control: every step readable and editable
  • Failures: retries and error workflows you design

Option C

Custom app

  • Fit: high volume, complex logic
  • Cost: highest build plus maintenance
  • Control: full, with tests and CI
  • Failures: whatever you engineer, including replay

The pick changes with logic and volume. Heavy business rules or very high order counts move you toward custom code, and a plain one-way sync of standard objects may not justify anything beyond a connector.

OptionUpfrontRecurringWhere cost surprises you
Prebuilt connectorLow: setup timeSubscription, often tied to volume or featuresWorkarounds for missing fields, a second tool for the second app
n8n middlewareMedium: build hoursHosting or plan, plus monitoring timeUpdates on self-hosted instances, credential rotation
Custom appHighest: design, build, testsHosting and a maintenance blockShopify API version upgrades, on-call time

Take a store with 5,000 orders a month, one CRM and three flows (illustrative). A connector costs a monthly fee and an afternoon of setup, until a custom field request forces a workaround or a second tool. An n8n build might take 40 to 80 hours plus hosting and a few hours of monthly upkeep. A custom app might cost several times that build, plus a standing maintenance block. Count the workarounds and the failures over twelve months, not only the invoice.

Shopify CRM integration data mapping

The mapping is the contract. It lists every field that moves, where it comes from, where it lands, which way it travels and who wins a conflict. Write it before the build and make the team sign off on it.

Data mapping flow

  1. 01Shopify eventCustomer, order, refund or consent change
  2. 02Map and dedupeMiddle layer: n8n or custom app
  3. 03Consent gateBlocked records skip the email platform
  4. 04Write to targetsCRM, ERP and email platform
  5. 05Store external IDWritten back to the Shopify record

Data flow from a Shopify event through mapping and a consent gate to the CRM, ERP and email, with an external ID written back

How a Shopify event becomes CRM, ERP and email records

Read the flow left to right. An event leaves Shopify, the middle layer maps it to CRM fields and deduplicates, a consent gate decides whether the email platform receives the contact, and the CRM record ID is written back to Shopify as an external ID.

ObjectShopify sourceCRM targetDirectionKey rule
CustomerCustomer, from customers/create and customers/updateContact (HubSpot) or Contact or Lead (Salesforce)Shopify to CRMMatch on email plus Shopify customer ID; store the ID in a custom property
OrderOrder, from orders/create and orders/updatedDeal, opportunity or order record, plus contact rollupsShopify to CRMUpsert on Shopify order ID; keep order number and currency
Line itemsOrder line itemsDeal line items or a custom objectShopify to CRMCopy SKU, quantity and price as at purchase
Refundrefunds/createFields or notes on the order recordShopify to CRMUpdate, never delete; store amounts
Cancellationorders/cancelledClosed deal stage with a reasonShopify to CRMKeep the record
Marketing consentCustomer email and SMS marketing consentMarketing status and consent propertiesShopify to CRM, unsubscribes both waysGate: imports never overwrite consent
Segment or tagNoneCustomer tag or metafieldCRM to ShopifyOne of the few write-backs

Use the table as a starting point, not a template. Your catalog, your sales process and your markets will change a few rows.

Customers and contacts

Match on email plus the Shopify customer ID. Email alone breaks when a customer changes address or checks out as a guest with another one. Store the Shopify ID in a custom CRM property so every later event updates the same record instead of creating a duplicate. In Salesforce, add an external ID field and upsert on it.

Guest checkouts have no customer ID. Decide whether they become contacts, and key them on email until an account exists.

Orders, line items and deals

An order maps to a deal in HubSpot, or an opportunity or order in Salesforce, depending on whether sales follows up. Pure e-commerce teams often skip deals and write order totals and last order date onto the contact instead. B2B teams with draft orders and quotes usually want a deal per order.

Keep the order number and the Shopify order ID on the record. Copy the currency with the amount and never convert silently.

Refunds and cancellations

A refund updates the order record. It never deletes it. Deletion breaks revenue reporting and the audit trail. Write the refunded amount, the date and a status such as partially refunded. Store amounts, not flags, because a flag cannot say how much. A cancellation moves the deal to a closed stage with a reason.

Consent is a gate, never a field to overwrite. Shopify records email and SMS marketing consent per customer. The CRM and the email platform should only mark a contact subscribed when Shopify says so, and an unsubscribe in either place must propagate. A CRM list import must never flip a contact back to subscribed.

In the US, the TCPA covers marketing texts. In Spain, GDPR applies, and several Latin American countries have their own data protection laws. Treat deletion requests the same way: one received in Shopify must reach the CRM. Confirm the rules with your legal advisor.

Webhooks, idempotency, retries and reconciliation

Cheap builds work on the happy path: a webhook arrives, the CRM accepts the record, done. Production is the other path. The CRM times out, Shopify sends the same event twice, a rate limit blocks you on a sale day. Failure handling is the part buyers never ask about, so it is the part to ask about.

Shopify webhooks are delivered at least once and not guaranteed in order, so duplicates and late events are normal. For a wider view of event pipelines, read our post on webhook pipelines for AI integrations. The safe path has five steps.

  1. Verify the signature

    Compute the HMAC of the raw body with your app secret and compare it with the X-Shopify-Hmac-Sha256 header.

  2. Acknowledge fast

    Return a 200 within seconds and push the event onto a queue.

  3. Deduplicate

    Look up the event key. If you have seen it, drop it.

  4. Upsert into the CRM

    Write by Shopify ID so a replay updates the record instead of duplicating it.

  5. Retry or park

    Retry with backoff. After the limit, move the job to a dead-letter queue and alert.

Verify, acknowledge, then process

Verify the HMAC signature on the raw body, answer with a 200 fast and do the CRM work later in a queue. If you call the CRM inside the webhook request, a slow CRM becomes failed deliveries, and Shopify will eventually stop calling. The handler below is a Next.js route handler. Check the header names against the docs before you copy it.

import { createHmac, timingSafeEqual } from "node:crypto";

// Placeholder: use Redis or a table with a unique constraint in production
const seen = new Set<string>();

export async function POST(req: Request) {
  // The HMAC covers the exact bytes Shopify sent, so read the raw body
  const raw = await req.text();
  const received = req.headers.get("x-shopify-hmac-sha256") ?? "";
  const expected = createHmac("sha256", process.env.SHOPIFY_API_SECRET!)
    .update(raw, "utf8")
    .digest("base64");

  const a = Buffer.from(received);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !timingSafeEqual(a, b)) {
    return new Response("Invalid signature", { status: 401 });
  }

  const topic = req.headers.get("x-shopify-topic") ?? "";
  const eventId =
    req.headers.get("x-shopify-event-id") ?? req.headers.get("x-shopify-webhook-id") ?? "";
  const key = `${topic}:${eventId}`;
  if (seen.has(key)) return new Response("Duplicate", { status: 200 });
  seen.add(key);

  // Hand off to a queue worker and answer fast
  await enqueue({ key, topic, payload: JSON.parse(raw) });
  return new Response("OK", { status: 200 });
}

async function enqueue(job: { key: string; topic: string; payload: unknown }) {
  // Replace with your queue client
  console.log("queued", job.key);
}

The in-memory set is a placeholder. In production the event key lives in Redis or a database table with a unique constraint, so it survives restarts and works across instances.

Idempotency keys and duplicate events

Idempotent means processing the same event twice gives the same result as processing it once. Record the event key before you act, and use upserts keyed on the Shopify ID instead of creates. Without that, a retry creates a second deal and your pipeline double counts.

Retries, dead-letter queues and rate limits

CRM APIs fail and throttle. Retry with exponential backoff and jitter so a thousand failed jobs do not hit the API in the same second. After a set number of attempts, park the job in a dead-letter queue: a holding place for events that need a human, with the payload and the error attached. An alert goes to a channel someone reads.

A queue also absorbs flash-sale spikes within the API limits of both sides. Ask any candidate what happens when the CRM is down for two hours. The answer should include the words queue, backoff and replay.

Nightly reconciliation as the safety net

Webhooks can be missed. A nightly job compares the previous day: orders, refunds and new customers in Shopify against the CRM. Gaps are repaired by fetching the missing records through the Admin GraphQL API and upserting them. The HubSpot developer docs list the batch and search endpoints that keep this job cheap.

The job also writes a short report. That report is how you know the sync works, instead of assuming it.

Safe sync path

  1. 01Webhook arrivesShopify sends the event
  2. 02Verify HMACInvalid signature is rejected
  3. 03Event ID lookupTopic and event ID checked
  • ADuplicateAlready seen, dropped
  • BNew event: CRM writeUpsert keyed on Shopify ID
    1. Record updatedSuccess ends here
    2. Retry with backoffOn failure, then dead-letter queue and alert
  • CNightly reconciliationCompares Shopify and CRM counts
    1. Repair gapsFeeds missing records back to CRM write

Failure path of a webhook sync: signature check, duplicate drop, CRM write, retries, dead-letter queue and nightly reconciliation

The safe sync path, from webhook to nightly repair

How to hire a Shopify integration team

Hiring for this is narrower than hiring a web agency. You want a team that has run syncs in production, not one with a polished storefront portfolio. Whether you search for a Shopify HubSpot integration agency, a Shopify Salesforce integration specialist or a Shopify ERP integration developer, the vetting is the same.

What to ask before you sign

Ask these eight questions and listen for mechanisms.

  • Who owns the Shopify app credentials, the CRM API keys and the workflow or repository?
  • How do you prevent duplicate contacts and deals when an event arrives twice?
  • What happens to events when the CRM is down for two hours?
  • How do you handle marketing consent and unsubscribes in both directions?
  • What do alerts look like, who receives them and how fast?
  • How do you backfill historical orders without hitting rate limits?
  • What is in the handover: mapping document, runbook, access, export?
  • What does maintenance cost after launch, and what does it cover?

A good answer names a mechanism: an event ID table, an upsert on an external ID, a dead-letter queue, a daily report. A weak answer says "we handle that".

A short SOW template

Put these items in the statement of work, one or two lines each:

  • Systems and objects in scope, with the mapping table as an appendix
  • Direction and source of truth for every field
  • Volume and freshness targets, written as numbers
  • Error handling, retries and the alerting channel
  • Backfill plan and cutover date
  • Acceptance tests, run against a sandbox
  • Handover: documentation, access, repository or workflow export
  • Support window after launch and what it covers

Red flags in proposals

These tend to predict trouble:

  • No mapping document before the build starts
  • A flat fee with no mention of retries or duplicates
  • They hold the API keys, or create the accounts under their own email
  • No sandbox, staging environment or test plan
  • No monitoring or alerts after launch
  • A promise of real time for everything

Who owns the sync after launch

Ownership has three parts: the accounts, the code and the alerts. Get all three in writing before the first invoice.

Ownership rule

The store owns the Shopify app credentials, the CRM API keys, the workflow or repository and the alert channel. The agency gets access, not custody. If the accounts belong to the agency, you cannot replace the agency.

A sync you own can be handed to another team in days. A sync they own has to be rebuilt.

Timeline and cost by integration count

Timeline tracks the number of integrations more than store size. The ranges below are illustrative, typical of projects like these, not guarantees.

For the recommended path, the phases run like this. Each extra integration adds its own mapping and test cycle on top.

  1. Week 1

    Discovery and mapping

    Inventory the systems, agree the mapping table, the source of truth and the freshness targets.

  2. Weeks 2 to 3

    Build the first sync

    Webhook intake, queue, upserts, retries and alerts, tested against a sandbox.

  3. Week 4

    Backfill and parallel run

    Load history and compare totals against the existing process.

  4. Week 5

    Cutover and monitoring

    Switch over at a recorded timestamp and watch the reconciliation reports.

Maintenance is part of the budget, not an afterthought. Plan a recurring block of hours for API version upgrades, credential rotation and alert triage, rather than a surprise invoice when a version is retired.

One CRM, one direction

Customers, orders and refunds into HubSpot or Salesforce typically take three to five weeks from kickoff to cutover (illustrative). Most of that time is the mapping workshop and testing, not typing code.

CRM plus ERP plus email

Adding an ERP and an email platform is not additive. The systems interact: ERP stock and prices affect what the CRM shows, and consent has to reach both. An illustrative range is eight to fourteen weeks. The ERP is the usual risk, because legacy systems expose limited APIs or only batch exports. Our post on API and legacy system integrations goes deeper.

Backfill and cutover

Backfill loads history, using Admin GraphQL bulk operations rather than paging through orders one request at a time. Run the new sync in parallel with the old process for a week or two, compare totals, then cut over at a recorded timestamp. Once the core sync is stable, you can layer automation on top, as in our post on Shopify and AI automation.

How werun.dev builds and monitors these syncs

We build Shopify CRM integration work with n8n or a Next.js custom app, and we choose by logic and volume, not preference. The process is the same either way.

Build: mapping first, code second

Week one is a mapping workshop. The output is the table, the source of truth for each field, the consent rules and the acceptance tests. Then we build against a Shopify development store and a CRM sandbox, with idempotent writes, retries and a dead-letter queue from the first commit. Our Shopify work includes Shopify Plus and store operations, so we know what the store side tolerates.

Monitor: alerts and reconciliation reports

Every sync ships with alerts to a channel you own and a daily reconciliation report: counts on both sides, mismatches repaired and jobs waiting in the dead-letter queue. A quiet channel means the numbers matched.

Run: Care plan or Retainer

The Care plan covers monthly maintenance: API version upgrades, credential rotation and alert triage. The Retainer covers ongoing change, such as a new object or a new system. You hold the accounts and the code. We hold access, not custody. The integrations service page lists what we connect.

Where to start

Three moves, in this order:

  1. Inventory. List every system that touches a customer or an order, and what each one needs to know.
  2. Draft the mapping. Use the table above, mark the source of truth per field and write freshness targets as numbers.
  3. Shortlist two or three teams and send each the same brief and the same eight questions.

If you want a second opinion on the mapping or a quote, start from our integrations service page and tell us which systems you run.

Frequently asked questions

How much does a Shopify CRM integration cost?

It depends on the option: a connector is a recurring subscription, n8n is build hours plus hosting, and a custom app is the largest build plus maintenance. Cost grows with the number of systems, two-way sync, custom objects and backfill. Ask for a price tied to a mapping document and a separate line for maintenance.

How long does it take to connect Shopify to a CRM?

As an illustrative range, three to five weeks for one CRM in one direction, and eight to fourteen weeks for a CRM plus an ERP and an email platform. Backfill and a parallel run add time. Most of the schedule goes to mapping and testing.

Should I use a Shopify app connector or hire a developer?

Use a connector when you sync standard objects in one direction with no custom rules. Hire a team when you need custom fields, conditional logic, a second system or visibility into failed records.

Can n8n connect Shopify to HubSpot or Salesforce?

Yes. n8n has Shopify, HubSpot and Salesforce nodes, plus an HTTP Request node for endpoints they do not cover. A Shopify webhook can trigger a workflow that maps the payload, writes to the CRM and handles errors.

What data should sync between Shopify and my CRM?

Start with customers, orders, refunds and marketing consent. Add products, inventory and subscriptions only when a team uses them. Sync only the fields someone acts on, and decide the source of truth for each one.

Who owns the integration after the agency finishes?

You should. The store owns the Shopify app credentials, the CRM API keys, the workflow or repository and the alert channel, and the agency works with access you grant. Put this in the statement of work, along with a handover of documentation.

Running into this on your own stack?

Tell us the platform and the problem. We'll tell you what it takes and who does it.

No commitment. Just a conversation.