# Shopify connector

> Connect a Shopify store with a custom app. Orders, refunds and customers join each customer profile, the attribution report and Meta.

Source: https://datacenter.so/docs/shopify-connector
Section: Measure

The Shopify connector reads your store's orders, refunds and customers and adds them to each [customer profile](https://datacenter.so/docs/customer-profiles). Sales also show in the [attribution report](https://datacenter.so/docs/attribution-report), and live sales can go to Meta.

It is on paid plans: Solo, Studio, Agency and Custom. Free does not include it.

**Connect with Shopify (when shipped).** A one-click login: type your shop address, click **Connect with Shopify**, approve Datacenter in the new tab, and you are done, with no app to make. Until it is switched on, use the steps below.

Datacenter only reads. The app you make has read access only, so it cannot change your store.

## Make a custom app

Shopify connects through a custom app that you make for your own store. These steps follow Shopify's help pages as of October 2026. Shopify changes its screens often, so a button may have a slightly different name.

1. In your Shopify admin, go to **Settings**, then **Apps**. Click **Develop apps**, then **Build apps in Dev Dashboard**.
2. In the Dev Dashboard, click **Create app** and name it `Datacenter`.
3. Make a version of the app. Keep the app address Shopify suggests. Under access scopes, add:
   - `read_orders`
   - `read_customers`
   - `read_all_orders`, to import the full 90 days. Without it, Shopify shows apps only the last 60 days of orders.
4. Release the version.
5. Install the app on your store.
6. In the app's settings, find the **Client ID** and **Client secret**.

You need to be the store owner, or have the **App development** permission. Shopify's guide: [custom apps](https://help.shopify.com/en/manual/apps/app-types/custom-apps).

This works when the app and the store belong to the same Shopify organization, which is the case when you make the app from your own store's admin. An agency connecting a client's store should make the app from that store.

## Connect

1. In Datacenter, open your site, then **Settings**, then **Integrations**. Next to **Shopify**, click **Connect**.
2. Type your shop address, such as `my-shop.myshopify.com`. Find it under **Settings**, then **Domains**.
3. Paste the **Client ID** and **Client secret**, and click **Connect Shopify**.

Datacenter gets an access token from Shopify with the client ID and secret. It checks the app has `read_orders` and `read_customers`, and says which one is missing if not. Shopify's tokens last 24 hours, so Datacenter gets a new one when it runs out.

The client secret is stored encrypted. It is never shown again, and it never appears in logs.

### An app made in the Shopify admin before 2026

Older custom apps show an **Admin API access token** (it starts with `shpat_`) and an **API secret key**. Leave Client ID empty, paste the API secret key in **Client secret**, and paste the token under **Made your app in the Shopify admin before 2026?**

## What happens next

- **The first import** reads orders from the last 90 days. A busy store can take a few hours, since each run reads a small batch. Integrations shows **Importing** and a count.
- **Webhooks.** Datacenter adds five webhooks to the app for you: `orders/paid`, `orders/updated`, `refunds/create`, `customers/create` and `app/uninstalled`. They go to `https://datacenter.so/hooks/shopify/...`. New orders then show up in seconds. The connector's page says whether they were added.
- **Every 15 minutes**, Datacenter also reads orders that changed since its last check, in case a webhook was missed.
- **Sync now** starts a check at once.

Each webhook is checked with the `X-Shopify-Hmac-Sha256` header and your client secret, and must come from your shop. Anything else is refused. Datacenter then reads the order again from Shopify, so it never trusts the webhook body alone.

## What shows up on a customer

| Shopify | On the customer |
|---|---|
| A paid order (or refunded later) | **Order**, with the total and product names |
| A partly paid order | **Order**, at what was paid so far. It rises as the rest is paid. |
| A refund | **Refund**, which lowers revenue |
| A new customer | A profile, with no order yet |

Orders that are not paid yet, such as cash on delivery, show up once they are paid.

Orders and revenue add up into the customer's lifetime value. Revenue adds up in the customer's first currency.

## Who the customer is

Datacenter finds the customer by:

- the Shopify customer id,
- the email and phone on the order (hashed with SHA-256, the way Meta asks),
- the visitor's first-party id in the cart attribute `_dc_id`.

## Where the sale came from

Shopify keeps the first and last visit before an order, with their landing pages and UTM tags. Datacenter reads them, along with click ids such as `fbclid` and `gclid` on the landing page. They move the customer's first and last touch, and the order shows its `utm_source` and `utm_campaign`.

For a full journey across visits, pass the first-party id to the order. Your site needs [90-day tracking](https://datacenter.so/docs/tracking-modes) and the 90-day tag on your theme. Then add this before `</body>` in your theme's `theme.liquid` (**Online Store**, **Themes**, **Edit code**):

```html
<script>
  (function () {
    var m = document.cookie.match(/(?:^|; )_dc_id=([a-f0-9]{32})/);
    if (!m) return;
    fetch('/cart/update.js', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ attributes: { _dc_id: m[1] } })
    });
  })();
</script>
```

It saves the id on the cart, and Shopify copies cart attributes to the order. The underscore keeps it out of sight at checkout. With **Wait for consent** on, the cookie only exists after the visitor agreed, so nothing is passed before that.

UTM tags saved as cart attributes named `utm_source`, `utm_campaign`, `utm_content` and `utm_term` are read too, when Shopify has no journey for the order.

## Goals and Meta

Synced orders count as the **Purchase** event. They reach any goal on the event `Purchase`.

When that goal is set to send to Meta (see [Meta Conversions API](https://datacenter.so/docs/meta-conversions-api)), a new order goes to Meta once:

- Only live orders: ones placed in the last 24 hours. The 90-day import never sends old orders.
- The hashed email and phone go along, and the buyer's IP address and browser when Shopify kept them.

Meta has no documented way to change a sale once it is sent, so a refund is not sent to Meta. Google Ads and Microsoft Ads do take refunds: see [Refunds](https://datacenter.so/docs/send-results-to-ad-accounts#refunds).

### The event_id rule

The connector uses `shopify-` and the order id as the `event_id`, such as `shopify-5523018432`. That is the same id the [Events API Shopify example](https://datacenter.so/docs/events-api#from-a-shopify-webhook) uses.

If you also send orders from the browser or the Events API, use that `event_id`, or send the order number as `order_id`. Then:

- Datacenter counts the order once on the customer.
- An order already sent to Meta from the browser or the Events API is not sent again by the connector, and the other way round.

The order id, the order name (`#1042`) and the order number (`1042`) all match the same order.

## The attribution report

Synced orders appear in the [attribution report](https://datacenter.so/docs/attribution-report) on their real date, under **All goals** and under a goal on `Purchase`. An order that your site also sent as an event, with the same `event_id` or `order_id`, is counted once.

Synced orders do not change your visitor stats and do not count toward your plan's events.

## If something goes wrong

Integrations shows **Needs attention** with the reason:

- **Shopify did not accept the client ID and secret.** Check them, and that the app is installed on this store. Paste them again under **Paste new app details**.
- **The app is missing read_orders.** Add the scope in a new version of the app, release it, then paste the details again.
- **Shopify is busy right now.** Nothing to do. Datacenter tries again every 15 minutes. This shows only after 6 hours with nothing read; a shorter outage is in the sync log alone.
- **Paused. Connectors are on paid plans.** The plan changed to Free. Sync starts again after an upgrade.

The connector's page lists the last 50 runs and webhooks. Keys and personal data are never shown there.

## Disconnect

Click **Disconnect** on the connector's page. Datacenter removes the webhooks it added, then deletes the client secret and token at once. Orders already imported stay on your customers. To remove one person's data, use **Delete this customer** on their profile. You can also uninstall the app in Shopify.

If you uninstall a custom app you made, the connector shows **Needs attention**. Your data stays. Make the app again and paste its details.

## Privacy requests from Shopify

These apply when you connect with **Connect with Shopify (when shipped)**, which uses Datacenter's own Shopify app.

- **A customer asks for their data.** Shopify tells Datacenter. Datacenter emails you what it holds about that customer for each site linked to the store: contact details it keeps, what they are known by, totals, and their orders and visits. Send it to the customer with what your store holds.
- **A customer asks to be deleted.** Datacenter deletes their profile, its ids and the orders Shopify names, on each linked site. Their ids are never linked again on that site.
- **You uninstall the app.** Syncing stops at once and the login is deleted. 48 hours later, Datacenter deletes the store's orders, the profiles that only came from Shopify, and the connection. Profiles your site knows in other ways stay, with the Shopify sales taken off. Install the app again within 48 hours to keep the data.

The connector's log lists each request. It never shows the customer's details.
