WordPress 6 min read

WooCommerce orders syncing to the wrong Xero contact: what I check

WooCommerce invoices land on the wrong Xero contact, duplicate customers, or a catch-all account. Checklist I run: email match rules, guest checkout, contact sync settings, multi-currency, and plugin mapping before rewriting the integration.

WooCommerce orders syncing to the wrong Xero contact: what I check

A paid WooCommerce order lands in Xero under the wrong contact. Sometimes it attaches to a near-match with a similar name. Sometimes it piles onto a generic "WooCommerce" or "Website Sales" contact. Sometimes you get a duplicate customer every time the same buyer checks out as a guest. Your bank feed still balances, but aged receivables, statements, and sales by customer are a mess.

I see this a lot on stores that flipped on a Woo-to-Xero plugin, changed guest checkout, or started taking company invoices without cleaning contact matching. Below is the order I work through before I start rewriting the sync mapping on production.

Confirm what "wrong contact" actually means

Open the Woo order and the Xero invoice side by side. Note the billing email, billing company, and billing name on Woo. Then check which Xero contact the invoice used, whether a new contact was created, and whether an older contact with the same email already existed.

Three failure modes look similar from the shop floor:

  • Match on name instead of email, so "J Smith" and "John Smith" collide
  • Guest checkout creates a fresh contact every order because no account email is stable
  • A catch-all contact is configured for all web sales, so every invoice lands in one place by design

If the plugin is configured to force a single sales contact, that is not a bug. Fix the setting, or accept that customer-level reporting will never work from Xero alone.

Email is the real primary key

Most Woo-to-Xero connectors match contacts on email first. If the order email is blank, a placeholder, a shared inbox, or different from the account email, the matcher either creates a duplicate or attaches to whoever already owns that address.

I check:

  • Guest orders where the customer typed a typo in the email field
  • Logged-in customers whose account email differs from the billing email on that order
  • Checkout plugins that overwrite email with a company accounts address
  • Xero contacts that already share one email across two people (common in small firms)

On a test order I use a brand-new email that does not exist in Xero, complete checkout, and watch whether a clean contact is created. Then I place a second order with the same email and confirm it reuses that contact. If the second order still creates a duplicate, the match rule is broken or the plugin is matching on something else.

Guest checkout, accounts, and company names

Guest checkout is the usual duplicate factory. No WordPress user means the plugin has only the order billing fields. If the buyer sometimes uses a personal email and sometimes a company email, Xero grows two contacts for one customer.

Company name matching is worse. "Acme Ltd", "Acme Limited", and "ACME" are three contacts if the plugin falls back to name when email is missing or shared. I prefer email-only matching for web orders, with company stored as a field on the contact rather than as the match key.

Also watch B2B or quote plugins that put a sales rep email on the order. That can push every invoice onto the rep’s Xero contact.

Plugin settings: contact sync, create vs update

Open the Woo-to-Xero (or accounting) plugin settings and read the contact rules carefully. Typical toggles:

  • Create contacts automatically vs map everything to one sales contact
  • Update existing Xero contacts from Woo billing fields (can overwrite snail-mail addresses you maintain in Xero)
  • Use billing vs shipping details for the contact
  • Sync on thank-you page vs on a cron queue (delayed sync makes "wrong contact" look intermittent)

I turn off "update contact from every order" on live stores that already keep tidy Xero records. One bad checkout should not rewrite a customer’s postal address or tax number in Xero.

Multi-currency, tax, and organisation mix-ups

Wrong contact is sometimes the symptom of the wrong Xero organisation or the wrong invoice settings. Multi-currency stores can create contacts under a second org if API credentials were pasted into staging and production swapped. Tax-inclusive vs exclusive mismatches do not usually move the contact, but a failed invoice create can retry later against a fallback contact.

I verify the connected Xero org name in the plugin, confirm the OAuth token is for the live company (not a demo org), and check the plugin log for "contact created" vs "contact matched" on the affected order IDs.

Duplicates already in Xero

If Xero already has three contacts for the same email, the plugin’s "match" is undefined. It may pick the oldest, the newest, or the first alphabetical. Cleanup in Xero (merge contacts, keep one email per customer) often fixes more tickets than another plugin update.

I export contacts with that email, merge in Xero, then re-push or credit-and-rebill only the invoices that must sit on the surviving contact. Do not mass-delete contacts that have payments against them.

When to stop guessing

If a unique email creates a clean contact, a repeat email reuses it, guest typos explain the one-offs, and only the catch-all or name-match setting is wrong, fix the setting and document it for whoever runs the shop. If matching still invents duplicates with a stable email, or invoices flip between two orgs after a credential refresh, stop toggling live sync during peak sales. At that point you want the plugin log, the Xero API contact payload for one order, and someone who has traced that connector’s match code before.

Do not "fix" production by wiping all Woo-created Xero contacts. You will orphan open invoices and break payment allocation.

Need this sorted properly? If Woo orders keep landing on the wrong Xero contact, I dig into email match rules, guest checkout, plugin contact settings, and the duplicates already in Xero. Happy to take a look before month-end reporting gets worse.

WordPress & WooCommerce support →

Most of these tickets come down to email matching, guest checkout creating a new contact every time, or a catch-all sales contact that was never meant for customer-level reporting. Confirm one clean test email round-trip first, then fix the match rules so the next paid order hits the right person in Xero. Cheers.

Need a hand with this?

Get help with a broken order journey, custom store features or ongoing WooCommerce care.

A related project

A custom price history feature for WooCommerce

Bespoke plugin work to record product price changes and present the history by date, delivered through an agency.

Talk directly to Adam

Share this article

Back to Blog