NIKOLA

Making the storefront and the ERP agree with each other

Your ERP is the system of record. Your store is where the money comes in. When they disagree — stock that is not really there, a price nobody honours, an order that never reaches the warehouse — the disagreement always costs more than the integration would have.

YOU ARE PROBABLY HERE BECAUSE

  • stock on the site does not match the warehouse
  • somebody re-keys orders into the ERP every morning
  • your connector cannot express the pricing you actually use
NetSuiteSAPAcumaticaMacollaSalesforceMicrosoft DynamicsHubSpotREST & SOAPFlat file & SFTPWooCommerce

What I can do for you

Whether you have no integration, a connector you have outgrown, or one that keeps breaking, the first step is the same.

FIXED · 3–5 DAYS

Reconciliation report

A written account of exactly where your storefront and your ERP currently disagree — stock, pricing, orders, customers — and why. Usually more revealing than anyone expects, and it is what a sensible quote gets built on.

FIXED · 6–10 WEEKS

New integration build

Two-way sync built around your rules: products, stock, contract pricing, parts, orders and customers. Queued workers with retry, idempotent writes so nothing duplicates, and a drift report that catches disagreement in days rather than at stocktake.

SCOPED AFTER THE REPORT

Extend or replace a connector

Keep the off-the-shelf connector for the ordinary flows and build only the parts it cannot express, or replace it outright. I will tell you which is cheaper, and it is often the first.

FIXED · 2–5 WEEKS

CRM and lead flow

Website leads reaching Salesforce, Dynamics or HubSpot with their source intact, routed to the right list and owner, deduplicated against what is already there, and queued so a slow API never costs you a form submission.

RETAINER OR HOURLY

Take over an existing integration

Inheriting something built by someone who has moved on. Starts with the reconciliation report, then stabilising, then owning it.

Book a consultation

Forty-five minutes, no charge.
I will tell you which of these you need, including when it is the cheapest one.

The lesson that shaped how I build these

The first version I ever built was real time. Every product page load asked the ERP for live stock and live pricing. It felt like the right answer — the data is never stale, there is nothing to reconcile, and the demo is impressive.

Then the ERP had a bad week, and so did the shop. API governance limits, latency on every page view, and the discovery that when the ERP goes down for maintenance, a storefront that queries it live goes down with it. That is not an ERP problem. That is an architecture problem, and it was mine.

What replaced it was a scheduled pull: the store keeps its own copy, a job brings products, orders, customers, parts, stock and pricing across on a cycle, and the storefront never talks to the ERP during a page view. Slightly staler. Enormously more reliable.

REAL TIME · WHAT I BUILT FIRST Customer opens a product page WooCommerce waits for an answer ERP live stock and price every page view is an API call governance limits, rate caps ERP slow → shop slow ERP down → shop down SCHEDULED PULL · WHAT REPLACED IT Customer opens a product page WooCommerce answers from its own data Sync worker queued, retried, logged ERP talked to on a schedule page loads never touch the ERP ERP down → data goes stale, shop keeps trading failed pulls retry, nothing is lost drift report shows disagreements
The trade is freshness for reliability, and for almost every store that is the right trade. Where a number genuinely must be live — a stock check at add-to-cart on a low-stock line, say — that one call can be made real time while everything else stays on the schedule. Choosing per field rather than per system is the part most integrations get wrong.

When you have outgrown the connector

Most WooCommerce and ERP integrations start with an off-the-shelf connector, and for a lot of businesses that is the right answer — it is cheaper, faster and supported by somebody else. I am not here to talk you out of one.

But connectors ship a fixed set of workflows. They map orders to sales orders, push stock one way, and handle the cases their vendor decided to handle. The moment your business does something the connector did not anticipate, you are choosing between changing how you trade and building something.

SIGNS YOU HAVE OUTGROWN IT

What people describe on the call

  • Contract pricing per customer that the connector cannot express
  • Configurable or made-to-order products arriving as a text note
  • Stock across several warehouses collapsed into one number
  • Somebody re-keying orders by hand every morning anyway
  • Kits, assemblies and parts that do not map to flat items
  • Sync running slowly enough that the catalogue is a day behind
  • Governance or API rate limits being hit at busy times
  • No way to see where the two systems currently disagree
WHAT REPLACING IT LOOKS LIKE

Built around your rules, not the vendor's

  • Ownership agreed per field, written down, no exceptions
  • Pricing logic that matches what your back office actually agreed
  • Idempotent order writes, so a retry never duplicates
  • Queued workers with backoff instead of blocking page loads
  • A drift report showing exactly where the systems disagree
  • Room for the next thing the business decides to sell

A middle path exists and is often correct: keep the connector for the ordinary flows and build alongside it for the parts it cannot express. That is usually cheaper than a full replacement, and I will say so if it fits.

Which approach yours needs

Not a matter of taste, and not one answer for the whole system. Most builds use two of these at once — a nightly pull for the catalogue, an event-driven push for orders. It depends on your catalogue size, your ERP's API limits, and how much a wrong number costs you.

RARELY THE RIGHT DEFAULT

Real-time sync

The store queries the ERP during the request. Correct only when the data genuinely cannot be a few hours old and the volume is low enough that the ERP can carry it.

  • Every page view costs an API call
  • ERP latency becomes your page speed
  • ERP downtime becomes your downtime
  • Governance and rate limits hit at exactly the wrong moment
  • Caching layers end up bolted on anyway
FOR ANYTHING THAT MUST NOT WAIT

Event-driven push

Not a schedule and not a page load — something happens and a job fires. An order is paid, so it goes to the ERP now. A refund is issued, so the credit follows. The customer is not waiting on it and neither is a cron.

  • Triggered by payment, order creation, status change
  • Queued immediately, retried on failure
  • Idempotency keys so a retry never duplicates an order
  • Nothing lost if the ERP is down when it fires
  • The right default for orders, specifically
WHAT I BUILD BY DEFAULT

Scheduled pull with local truth

A background worker brings the ERP data across on a cycle. The storefront reads its own database and never blocks on an external system.

  • Page loads are as fast as any normal store
  • An ERP outage makes data stale, not the shop dead
  • Failures retry instead of vanishing
  • Every sync is logged, so disagreements are findable
  • Individual fields can still be real time where it matters

What actually moves between them

Direction matters as much as content. Most of the painful bugs in ERP integrations come from two systems both believing they own the same field.

RECORDWHAT IT INVOLVESDIRECTION
Products

Catalogue, descriptions, attributes, categories, variations, and the mapping between ERP item codes and Woo SKUs — which is where most projects lose their first week.

ERP → STORE
Stock levels

Quantities per warehouse or location, backorder rules, and what the storefront should say when the number is unreliable rather than simply low.

ERP → STORE
Pricing

List price, customer-specific contract rates, quantity breaks, and currency. Usually the field with the most business rules attached to it.

ERP → STORE
Parts and components

Assemblies, kits and configurable components, so a product built from parts prices and reserves stock correctly rather than as a flat item.

ERP → STORE
Orders

Placed orders pushed into the ERP for fulfilment, with idempotency so a retry does not create a duplicate — the single most expensive bug in this category.

STORE → ERP
Customers

Accounts matched or created on both sides, with tier and account type driving what the customer sees and pays.

BOTH WAYS
Fulfilment and returns

Shipment confirmations, tracking numbers and credits coming back so the customer's account reflects what the warehouse actually did.

ERP → STORE

CRM integration — the other system that thinks it owns your customers

An ERP owns stock, price and fulfilment. A CRM owns people and pipeline. Both believe they hold the authoritative customer record, and on most sites neither of them is right — the website has a third version nobody reconciles.

The work is mechanically similar to ERP integration and commercially quite different: sales cares about attribution and speed to follow-up, not about whether stock matched.

Lead capturefrom the site into the pipeline

Form submissions, quote requests, downloads and sign-ups pushed into the CRM as they happen — with the source, campaign and page they came from attached, so marketing can tell what actually generated the enquiry rather than guessing.

List and segment routingthe right list, automatically

Contacts added to the correct lists, segments or campaigns based on what they did — which product, which page, which form. Done properly this replaces somebody exporting a CSV every Monday morning.

Deduplication and matchingthe hard part

The same person fills in three forms with two email addresses over two years. Deciding what counts as the same contact, what updates and what creates, is a set of rules that has to be agreed rather than assumed — and it is where most CRM integrations quietly rot.

Two-way contact syncaccounts and customers

Registered customers, order history and lifetime value flowing into the CRM so sales can see what someone actually bought, and CRM-side changes flowing back so the account area reflects what the salesperson agreed.

Deals and opportunitieswhere the site starts the sale

A quote request or a high-value abandoned cart creating a real opportunity with the right owner, value and stage, rather than an email somebody has to re-key.

Attribution that survivesfirst touch to closed deal

Carrying campaign and referral data through the form, into the CRM, and onto the deal — so the answer to "where did this customer come from" exists six months later when someone finally asks.

HubSpot specificallyincluding getting off it

Forms, lists, workflows, landing pages, and the CMS. I have built an entire site inside HubSpot's own builder, which means I can tell you honestly what it is good at and what it is not — and I can migrate a site off it without losing the tracking and the contact history that make it worth having in the first place.

Rate limits and reliabilitysame discipline as ERP

CRM APIs have quotas too, and a form submission must never fail because a third party is slow. Submissions are queued and pushed in the background, retried on failure, and never lost — the visitor sees a confirmation regardless.

How a build runs

The first two steps decide whether the rest is a six-week job or a six-month one, and they happen before any code is written.

  1. Read the ERP before promising anything

    Which API, which version, what the rate limits and governance rules actually permit, whether your licence includes the integration module, and who inside your organisation owns the data. That last question is political and it will decide more than the technical answers.

  2. Agree who owns each field

    One system is authoritative per field, written down, no exceptions. Both systems believing they own price is how stores end up selling below cost at three in the morning.

  3. Map identifiers

    ERP item codes to SKUs, customer records to accounts, and a documented answer for every record that exists on one side and not the other. Nobody enjoys this week. Skipping it costs a month later.

  4. Build the worker, not the endpoint

    Queued jobs with retry and backoff, idempotency keys so nothing is created twice, and a log of every sync. Built to be resumable, because at some point it will fail halfway through.

  5. Reconcile continuously

    A scheduled comparison that reports where the two systems disagree, and how badly. Integrations do not fail loudly; they drift quietly. The drift report is what catches it in days rather than at stocktake.

  6. Run both in parallel before cutting over

    The new sync runs alongside the old process, writing nowhere, for long enough to prove it agrees. Then it takes over.

Where this has been done

Arkansas Lighting

Storefront built from scratch and integrated two ways with NetSuite and Macolla. Products, orders, customers and parts moving in both directions, with a WebGL shade configurator running on the same catalogue data. Started real time, moved to scheduled pull after the ERP took the storefront down with it, and maintained for nine years afterwards. Nine years of the same two systems agreeing, and the same developer answering when they did not.

NetSuite · Macolla
products · orders · customers · parts
2016 — 2025

Wholesale and dealer catalogues

Contract pricing and account tiers resolved against the system of record so that what a logged-in dealer sees matches what the back office agreed. Several engagements across furniture and home goods distribution.

B2B pricing sync
tiers · contract rates · dealer portals

What this does not include

Work inside the ERP

I build and own the storefront side of the integration. Customisation within NetSuite, SAP or Acumatica belongs to your ERP partner, and I will work alongside them rather than pretend otherwise.

Configuring the CRM itself

Pipeline design, workflows and reporting inside Salesforce or HubSpot belong to whoever runs your sales operation. I build the bridge and make sure what arrives is clean.

Fixing bad ERP data

If item codes are inconsistent or customer records are duplicated in the ERP, syncing faithfully reproduces that mess in the store. I will show you what I find, but cleaning the source is yours.

Choosing an ERP

That decision involves finance, operations and warehousing far more than it involves the website. I can tell you which ones are pleasant to integrate with, and that is a small part of the question.

A promise of real time

If someone has told you live sync is simply better, they have not been on call when the ERP goes down mid-afternoon.

Questions I get asked

How current will our stock numbers be?

As current as the sync cycle, which is usually hourly for stock and daily for the catalogue. Where a specific line genuinely needs a live check — high value, low stock, prone to overselling — that one call can be made at add-to-cart while everything else stays scheduled. It is a per-field decision, not an all-or-nothing one.

What happens if the ERP goes down?

The shop keeps trading on the data it already holds and the queued jobs retry when the ERP returns. Orders placed during the outage are held and pushed once it is back, with idempotency keys so nothing is duplicated. Data goes stale; nothing is lost.

Can you connect to an ERP you have not worked with?

Usually yes, and I will tell you honestly how much of my experience transfers. The integration patterns — ownership per field, identifier mapping, idempotent writes, reconciliation — are the same everywhere. What differs is the API, its limits and its documentation. My depth is greatest with NetSuite and Macolla; SAP and Acumatica I have worked with less.

How long does a build take?

For a straightforward catalogue and order sync, six to ten weeks. The variables are how clean the ERP data is, how many pricing rules exist, and how quickly someone on your side can answer questions about the data. Configurable products and multi-warehouse stock add time.

We are hitting NetSuite governance or rate limits. What now?

Usually it means something is querying the ERP during a page load, or a sync is making one call per record where it could batch. The fix is architectural rather than a tuning exercise: move the work into a queued job, batch the reads, and let the storefront answer from its own copy. That is the same change I made after my first real-time build fell over.

Our connector cannot handle our pricing. Do we have to replace it?

Not necessarily. Often the cheapest answer is to keep the connector for catalogue and orders, and build only the pricing resolution alongside it. Full replacement is worth it when several things are being worked around at once, or when someone is re-keying data daily regardless.

We already have an integration and it keeps breaking. Can you take it over?

Yes, and it is a common way this starts. The first piece of work is usually a reconciliation report showing exactly where the two systems currently disagree, which tends to be more revealing than anyone expects.

Do you work through agencies or alongside our ERP partner?

Both, regularly. I take the website side and stay in my lane, which ERP consultancies generally appreciate because most web developers do not.

Tell me which ERP and roughly how many SKUs

That plus your order volume is usually enough for me to say on a call whether this is a six-week job or a six-month one.

Book a consultation