---
title: 'Shopper Profile Sync: Native Two-Way Sync Between SFCC and Salesforce'
canonical_url: 'https://okater.com/posts/sfcc-shopper-profile-sync/'
markdown_url: 'https://okater.com/posts/sfcc-shopper-profile-sync/index.md'
content_type: article
site_name: SFCC Field Notes - Oleksandr Katerynchuk
date: '2026-10-06'
lastmod: '2026-10-06'
author: Oleksandr Katerynchuk
description: >-
  How to set up Shopper Profile Sync between B2C Commerce and a Salesforce org.
  A video walkthrough, a checklist you can follow along with, how each sync
  direction actually works, and the fine print behind "two-way".
tags:
  - sfcc
  - integration
---

If you ever had to get B2C Commerce customers into Salesforce Core, you know it used to be a project of its own. Most of the time that project was [b2c-crm-sync](https://github.com/SalesforceCommerceCloud/b2c-crm-sync), an open-source enablement framework. It was designed to teach the B2C customer data strategy, it is maintained by the community, and its README is very clear about what that means:

> Please remember that this project **should not be treated as Salesforce Product**. [...] Customers and partners implement this at-will with no expectation of roadmap, technical support, defect resolution, production-style SLAs.

So you owned all of it: a Node CLI, SFDX deployments, OCAPI and WebDAV permissions, JWT certificates, an Account Manager client, plus the Apex, Flows and Platform Events on the Core side. And it hasn't seen an update in about three years.

Now there is a native way. **Shopper Profile Sync** went GA in June 2026. You connect your B2C Commerce instance to a Salesforce org from Business Manager, set up a few rules in Core, flip a switch, and registered shoppers start showing up as Person Accounts. Edit one of those Person Accounts in Core, and the change lands back in Commerce about a minute later.

The Salesforce Connection you create along the way is also what Merchant Agent and Shopper Agent build on.

I recorded the whole setup on a sandbox, from connecting the two clouds to watching a profile travel both ways.

[Setting up Shopper Profile Sync between SFCC and Salesforce](https://customer-s2hy6afr8h81a1gk.cloudflarestream.com/41ed15c8d0a79a0dd00096400232da08/watch)

## Shopper Profile Sync or Unified Profile Sync?

Same feature, two names. The documentation, the release notes and the card in Business Manager all say **Shopper Profile Sync**. The feature switch says **Enable Unified Profile Sync Feature**, and the system job and the Business Manager API use "unified profile" too. I'll stick with Shopper Profile Sync here, but if you are searching for answers, try both.

## How it works: two directions, two mechanisms

"Two-way sync" sounds symmetric. It isn't, and that is the most useful thing to understand before you start.

```mermaid
flowchart LR
    S[Shopper registers<br/>or edits profile] --> B2C[(B2C Commerce<br/>customer)]
    B2C -->|"scheduled job<br/>every 30 min, 10 min on ODS"| PA[(Salesforce<br/>Person Account)]
    PA -->|"event, about 1 min"| B2C
    A[Service agent<br/>edits record] --> PA
```

**Commerce to Salesforce is a scheduled job.** A system job picks up new and changed profiles and pushes them to Salesforce. It runs every 30 minutes in production and every 10 minutes on on-demand sandboxes, up to 100,000 records per run. That cadence arrived in 26.9. Before that it was hourly, so if you read older threads complaining about the wait, that's why.

You don't have to guess when the next run is. The Shopper Profile Sync card under **Administration → Global Preferences → Salesforce Connection** shows the last sync status and the next scheduled sync:

<figure>
  <img src="/images/posts/sfcc-shopper-profile-sync/bm-salesforce-connection.webp" alt="Business Manager Salesforce Connection page with an active connection and the Shopper Profile Sync card showing Last Sync Status: Synced and the next scheduled sync time" width="1640" height="940" loading="lazy">
  <figcaption>The card tells you exactly how long you'll be staring at the Accounts list.</figcaption>
</figure>

**Salesforce to Commerce is event-driven.** When someone edits a synced Person Account in Core, the change is pushed to Commerce right away. The docs say about a minute. In the video I renamed a shopper in Core, refreshed the storefront, and the new name was already there.

### The fine print behind "two-way"

- **Person Accounts are only created from the Commerce side.** If you create a Person Account by hand in Core, no B2C customer appears.
- **Updates go both ways, but only for linked records.** That means shoppers who went through the sync from Commerce first, or who got matched to an existing Person Account by your duplicate rules (more on that below).
- **Only registered shoppers sync.** Guest checkouts don't create Person Accounts through this feature.

There is one more nuance for new registrations. Since 26.8, a fresh registration can create the Person Account in near real time instead of waiting for the next job run, on headless storefronts (PWA Kit, Storefront Next). My sandbox runs SFRA, and the new account waited for the job, which is what you see in the video.

## Before you start

- **A B2C Commerce sandbox on a recent release.** The feature moved fast between 26.6 and 26.9, so the newer the better.
- **A Salesforce org to pair with.** For testing, use a Salesforce sandbox or a demo org, not production. The connection is one to one and Person Accounts can't be switched off, so experiments belong somewhere you can throw away. For the real setup, the org needs Enterprise or Unlimited edition with Data 360 provisioned.
- **The Salesforce Connection page in Business Manager.** If **Administration → Global Preferences → Salesforce Connection** isn't there, check **Feature Switches** for **Unified Commerce Configuration**. If the page is there but the Shopper Profile Sync card isn't, enable **Enable Unified Profile Sync Feature**.
- **Pick your pairing.** One B2C Commerce instance connects to exactly one Salesforce org, and you can't split it per site. If you run several country sites on one realm, they all land in the same org.

## The setup checklist

This follows the official [Configure Shopper Profile Sync](https://help.salesforce.com/s/articleView?id=cc.b2c_configure_shopper_profile_sync.htm&type=5) guide, in the order that actually works, with the bits that confused me spelled out. Tick the boxes as you go (they don't survive a page refresh, so keep the tab open).

<ul class="checklist">
  <li>
    <label><input type="checkbox"> <span><a href="https://help.salesforce.com/s/articleView?id=cc.b2c_connected_comm_salesforce_connection.htm&amp;type=5">Connect your B2C Commerce instance to Salesforce</a>. In Business Manager go to <strong>Administration → Global Preferences → Salesforce Connection</strong> and hit <strong>Connect</strong>.</span></label>
    <ul>
      <li><label><input type="checkbox"> <span>The login opens on <code>test.salesforce.com</code>. That's right for a Salesforce sandbox. For a production or developer org, change <code>test</code> to <code>login</code> in the address bar before you log in, otherwise it won't work.</span></label></li>
    </ul>
  </li>
  <li>
    <label><input type="checkbox"> <span><a href="https://help.salesforce.com/s/articleView?id=sales.account_person_enable.htm&amp;type=5">Enable Person Accounts</a> in Salesforce Setup. Many demo orgs already have them on.</span></label>
    <ul>
      <li><label><input type="checkbox"> <span>Heads up: once Person Accounts are enabled, they can't be turned off. No big deal in a demo org, a real decision in a production one.</span></label></li>
    </ul>
  </li>
  <li>
    <label><input type="checkbox"> <span><a href="https://help.salesforce.com/s/articleView?id=cc.b2c_set_up_person_account_duplicate_rules_for_shopper_profile_sync.htm&amp;type=5">Set up Person Account duplicate rules for Shopper Profile Sync</a>. Matching rules first, then duplicate rules.</span></label>
    <ul>
      <li><label><input type="checkbox"> <span>Create the <strong>3 matching rules</strong> on the Person Account object, using the names and criteria from the docs. For example, the registered shopper rule matches on <strong>Commerce Customer Reference</strong> and <strong>Commerce Organization Reference</strong>, both <strong>Exact</strong>, <strong>Match Blank</strong> off, filter logic <code>1 AND 2</code>. Save and activate each one.</span></label></li>
      <li><label><input type="checkbox"> <span>Create the <strong>3 duplicate rules</strong>, one per matching rule: <strong>Bypass sharing rules</strong>, action on create and on edit set to <strong>Allow</strong>, <strong>Alert</strong> unchecked, <strong>Report</strong> checked. Attach the matching rule, add the condition from the docs (for the registered shopper rule that's <strong>Commerce Customer Reference</strong> not equal to blank), then save and activate.</span></label></li>
      <li><label><input type="checkbox"> <span>Double-check <strong>Report</strong>. The docs say "no alert, report", which is easy to misread as "no report". If Report is off, the rule won't activate.</span></label></li>
    </ul>
  </li>
  <li>
    <label><input type="checkbox"> <span>Back in Business Manager, hit <strong>Get Started</strong> on the Shopper Profile Sync card and review the attribute mappings. The defaults are fine unless you have extra data to sync.</span></label>
    <ul>
      <li><label><input type="checkbox"> <span>If you do: the standard fields come mapped, and you can add up to 20 custom ones. Only simple types are supported (Text, Boolean, Integer, Long, Double), and a Salesforce field has to be visible to the integration user to show up in the list.</span></label></li>
    </ul>
  </li>
  <li>
    <label><input type="checkbox"> <span>Turn on <strong>Auto-Sync</strong>. Do this last, not earlier. Without active rules and complete mappings you get <em>"Unable to start synchronization. Please map all required fields and configure duplicate rules"</em>, and the status sits at <strong>Initialization Pending</strong>.</span></label>
  </li>
  <li>
    <label><input type="checkbox"> <span>Test <strong>Commerce → Salesforce</strong>: register a new customer on the storefront, wait for the next scheduled sync on the card, then check <strong>Accounts → All Person Accounts</strong> in Salesforce.</span></label>
  </li>
  <li>
    <label><input type="checkbox"> <span>Test <strong>Salesforce → Commerce</strong>: edit that Person Account in Salesforce (I added "SF Core" to the first and last name), then refresh the storefront account page or the customer in <strong>Merchant Tools → Customers</strong>. Give it about a minute.</span></label>
  </li>
</ul>

## Why three duplicate rules?

Setting up six rules by hand feels like a lot for "sync my customers", so it helps to know what they are for. The recommended set covers three situations: a registered shopper, a guest shopper, and a registered shopper claiming an earlier guest record.

That last one is the interesting case. A shopper checks out as a guest, and Order Management creates a Person Account for that order. A month later the same person registers on your storefront. Without the claim rule you end up with two Person Accounts for one human. With it, the sync finds the guest record, links it to the new shopper and updates it instead.

```mermaid
flowchart TD
    R[Registered shopper<br/>arrives from Commerce] --> M{Duplicate rules<br/>find a match?}
    M -->|"Already linked"| U[Update that<br/>Person Account]
    M -->|"Guest record from<br/>an earlier order"| C[Claim it and link<br/>to the shopper]
    M -->|"No match"| N[Create a new<br/>Person Account]
```

If your org already has Person Accounts from somewhere else, these rules are also what stops the first sync from flooding it with duplicates. Worth testing on a sandbox with realistic data before production.

## What about b2c-crm-sync?

If you are starting fresh, go native. If you already run b2c-crm-sync, it is worth looking at what you actually use, because the two don't cover exactly the same ground:

| | b2c-crm-sync | Shopper Profile Sync |
| --- | --- | --- |
| Support | Community project, no official support | Salesforce feature, supported |
| Setup | Node CLI, SFDX, OCAPI and WebDAV permissions, JWT certificates, Account Manager client | Connect in Business Manager, rules in Core |
| B2C Commerce API | OCAPI Shop and Data APIs (deprecated) | Built in, nothing to configure |
| Customer model | Person Accounts or Accounts and Contacts | Person Accounts only |
| Extras | Order on Behalf, agent password reset, address books, promotions view | Profile fields |
| Topology | Multiple instances, customer lists and sites | One instance to one org |
| Maintenance | Yours | Salesforce's |

There is one more reason to move: OCAPI. b2c-crm-sync talks to B2C Commerce through the OCAPI Shop API and Data API, and OCAPI was marked deprecated in April 2026. It still gets support and security fixes, but no new features, and SCAPI is where everything new lands. The README promises a port to the new APIs "in a future release", and with the project quiet for three years, I wouldn't wait for it.

If you only use b2c-crm-sync to get profiles into Core, Shopper Profile Sync replaces it with a lot less to maintain. If you rely on Order on Behalf or the Accounts and Contacts model, plan the move like a small project. There is no switch that migrates you.

## When it doesn't sync

A few places to look, roughly in the order I'd check them:

- **The card itself.** Last sync status and next scheduled sync answer most "where is my customer?" questions. Usually the answer is "the job hasn't run yet".
- **Initialization Pending.** Almost always missing or inactive duplicate rules, or required mappings that aren't complete.
- **No Shopper Profile Sync card.** It's the feature switch.
- **The system job.** It's called `sfcc-sync-unified-shopper-profiles` and shows up as a system job in Business Manager, so depending on your permissions you may not see it at all.

## Wrapping up

Connect the two clouds, enable Person Accounts, set up the three matching rules and the three duplicate rules (with Report on), turn on Auto-Sync last, and you have a supported two-way profile sync without a single line of custom code. Just remember the asymmetry: Commerce creates and syncs on a schedule, Salesforce only updates and does it almost instantly.

Next up is Merchant Agent, which uses the very same Salesforce Connection. Happy syncing. 🔄
