If your Shopify store has a loyalty app, a welcome flow or a custom integration that cares whether a customer "has an account", this one is worth ten minutes of someone's time. Shopify has changed what happens the first time a customer signs in, and the change is already live.
There's a wrinkle too. Some customers have already been switched over in one go, and your apps weren't told.
What Shopify has changed
Every customer record in Shopify has a state. The two that matter here are DISABLED, which means no active account, and ENABLED, which means they've created one.
Until now, customers using Shopify's customer accounts stayed DISABLED even after they'd signed in. That meant the Liquid check customer.has_account came back false for people who had plainly signed in.
According to a changelog entry posted on 28 October, and marked as effective from 17 October, that's changed. A customer's first sign-in now does three things:
- Sets Customer.state to ENABLED.
- Sends the customers/enable and customers/update webhooks.
- Makes customer.has_account return true from then on.
It applies to every sign-in method: email code, Shop, Google, Facebook, Apple and third-party identity providers. Shopify says this brings it into line with how legacy customer accounts activate.
On the face of it, that's a straightforward improvement. The data now says what you'd expect it to say.
The bit that needs a second look
Your customers now fall into three groups, and they don't all behave the same way.
Customers who signed in between 27 May 2024 and the date of the post. They're already ENABLED. Shopify did this in a one-time update that sent no webhooks. So if your app only learns about customers through webhooks, it never heard about any of them.
Customers who haven't signed in since 27 May 2024. They stay DISABLED until their next sign-in. That sign-in counts as a first sign-in, so it sets them to ENABLED and fires both webhooks. Someone who's been on your list for years can arrive looking brand new.
New customers signing in from now on. Simple enough. First sign-in, state changes, webhooks go out.
Shopify also warns against using updated_at to find the first group, because the one-time update didn't change it for all of them. Its advice is to query Customer.state directly. If your sync works by asking "what's changed since last time?", it's exactly the sort of job that could miss these people.
Who needs to care
Shopify's own line is "Most apps don't need changes", and I'd take that at face value. Plenty of stores will never notice this. But the entry lists four things that are affected:
- Anything reading Customer.state from the GraphQL Admin API.
- Anything listening for the customers/enable or customers/update webhooks.
- Anything consuming customer.state events from the Events API.
- Themes or Liquid code using customer.has_account.
The useful question is what your code does next. Shopify specifically mentions apps that send welcome messages, award loyalty points or sync records when they get the webhook or see an enabled state.
Think about what those look like in a typical custom setup. A welcome discount that goes out when customers/enable arrives was probably written on the assumption that it means "this person just joined". Now it means "this person just signed in for the first time since May 2024, or ever". That might be a long-standing customer who's been buying from you as a guest for years. Do you want them getting a new customer offer? Perhaps you do. It's just worth deciding on purpose.
The same goes for points. A sign-up bonus tied to that webhook will now pay out on a first sign-in, which may or may not be what your scheme's rules say.
And then there's anything that keeps its own copy of your customers. If your CRM, email tool or a custom integration holds an "account holder" flag, it may now disagree with Shopify about part of your list, because the one-time update never told it. You could end up with two systems quietly giving different answers to the same question, which is the sort of thing that turns up when someone builds a report six months later.
Themes are the easiest to check. If you show different content to account holders, or hide a "create an account" prompt based on has_account, more people will now see the account holder version. That should be better, but have a look rather than assume.
What I'd do
None of this is an emergency, and it's a small job for most stores.
- Search your custom apps and theme for customers/enable, customers/update, Customer.state and has_account. If nothing comes up, and your third-party apps aren't doing anything clever with account status, you're probably done.
- For each thing you find, ask whether "first sign-in" is the right trigger for what it does. That's Shopify's own suggestion, and it's the right question.
- If you keep customer data outside Shopify, query Customer.state and compare it with what you've got. Fix the gaps as a one-off. Don't trigger your welcome flow while you're doing it, or you'll email a lot of people who've been with you for ages.
- Check any third-party loyalty or email app that relies on account status. Ask the vendor how it's handled this, if the answer isn't in their docs.
- Have a quick look at your theme while signed in as a test customer.
The wider lesson is a dull one, but it's true. Webhooks tell you what happened, as long as nobody changed things behind them. Anything that depends on a copy of data from another system needs a way of checking it against the source now and then, because one day the source will change without sending you a message. A scheduled reconciliation job is rarely exciting, but it's what catches this sort of thing.
Want a hand?
We build and look after custom Shopify apps and integrations, and the API work that connects Shopify to CRMs, email tools and everything else. If you'd like someone to check how your setup handles this, or you've inherited an app and aren't sure what it's listening for, get in touch.
Cheers, Rob

