---
title: Identify Shop users
description: >-
  Get the Shop user public ID from a Shop Pay Wallet payment and from Sign in
  with Shop, then link both to a customer record in your own system.
source_url:
  html: 'https://shopify.dev/docs/api/commerce-components/pay/identify-shop-users'
  md: 'https://shopify.dev/docs/api/commerce-components/pay/identify-shop-users.md'
---

# Identify Shop users

Shop Pay Wallet and Sign in with Shop identify a buyer with the same value: the Shop user's public ID. Read it from the payment request receipt after checkout, store it on your own customer record, and resolve it again when the same person logs in later.

***

## What you'll learn

In this guide, you'll learn how to do the following tasks:

* Read the Shop user public ID from a payment request receipt.
* Store the public ID on a customer record in your system.
* Add Sign in with Shop to your login page and resolve the same public ID.

***

## Requirements

* A working Shop Pay Wallet integration. To set one up, refer to [Get started with Shop Pay Wallet](https://shopify.dev/docs/api/commerce-components/pay).
* Storefront API version `2026-10` or later, or `unstable`.
* A [Shop app](https://shopify.dev/docs/api/shop/guides/creating-a-client) with a client ID and client secret.
* A login page and a customer database that you control.

***

## Step 1: Get the public ID after a payment

The `ShopPayPaymentRequestSessionSubmit` mutation returns a receipt for the payment. Request `shopUser` on the receipt to get the public ID of the Shop user who authorized it:

## Mutation

```graphql
mutation shopPayPaymentRequestSessionSubmit($token: String!, $paymentRequest: ShopPayPaymentRequestInput!, $idempotencyKey: String!) {
  shopPayPaymentRequestSessionSubmit(token: $token, paymentRequest: $paymentRequest, idempotencyKey: $idempotencyKey) {
    paymentRequestReceipt {
      token
      processingStatusType
      shopUser {
        publicId
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

## Response

```json
{
  "shopPayPaymentRequestSessionSubmit": {
    "paymentRequestReceipt": {
      "token": "a607823b7ba40ddb4eede13822684b13",
      "processingStatusType": "ready",
      "shopUser": {
        "publicId": "4kQ9mLd2XbVw7NcRp1TgHs6y"
      }
    },
    "userErrors": []
  }
}
```

### Shop​User

| Field | Type | Description |
| - | - | - |
| publicId | String | The public ID of the Shop user that authorized the payment request. |

`shopUser` is nullable. It's `null` when Shopify can't attribute the payment to a Shop user, so complete the order without a Shop user link instead of treating the payment as failed.

***

## Step 2: Store the public ID

The public ID is a stable identifier for a Shop user. The same person returns the same public ID on every payment and every sign-in, so you can use it as the key that links a Shop user to your own customer record.

After the payment succeeds:

1. Create or update the customer record in your database, and save the public ID on it.
2. Start your own session for that customer, such as a signed session cookie.
3. Continue with your existing order confirmation flow.

***

## Step 3: Add Sign in with Shop to your login page

Your login page is hosted outside Shopify, so it signs users in with the OpenID Connect authorization code flow, using Shop as the identity provider. [Sign in with Shop](https://shopify.dev/docs/api/shop/guides/use-cases/sign-in) covers the Shop SDK `login` feature that renders the button, and [Sign in with a third-party identity provider](https://shopify.dev/docs/api/shop/guides/use-cases/external-login-page) lists every OIDC endpoint.

Redirect the user to `https://accounts.shop.app/oauth/authorize` with the following query parameters:

| Parameter | Value |
| - | - |
| `client_id` | Your Shop app's client ID. |
| `redirect_uri` | One of the redirect URLs registered on your Shop app. |
| `response_type` | `code`. |
| `scope` | `openid email`. |
| `state` | A random per-request value that you verify when the user comes back. |
| `code_challenge` | The S256 challenge for a per-request PKCE code verifier. |
| `code_challenge_method` | `S256`. |

After the user signs in, Shop redirects to your `redirect_uri` with a `code` parameter and your `state`.

**Use the right client ID:**

Use your Shop app's client ID here, not the `clientId` that you pass to the Shop Pay Wallet JavaScript SDK. The client ID used for Shop Pay Wallet JavaScript SDK will not currently work with the Shop SDK, and so will show an error in the sign in flow if you use it here.

***

## Step 4: Exchange the code for an ID token

Exchange the code from your backend, where the client secret stays private:

## Token request

```bash
curl -X POST https://accounts.shop.app/oauth/token \
  -d grant_type=authorization_code \
  -d code={code} \
  -d redirect_uri={redirect_uri} \
  -d code_verifier={code_verifier} \
  -d client_id={client_id} \
  -d client_secret={client_secret}
```

The response includes an `id_token`. Validate it before you trust anything in it:

1. Verify the signature against the keys at `https://accounts.shop.app/auth/jwks`.
2. Check that `iss` is `https://accounts.shop.app`, that `aud` is your client ID, and that `exp` is in the future.

The `sub` claim of a validated ID token is the Shop user's public ID, and the `email` claim is the address on the Shop account.

***

## Step 5: Log the user in

1. Look up the customer record whose stored public ID matches `sub`.
2. If a record exists, then start your session for that customer.
3. If no record exists, then create one from `sub` and `email`.

Because both surfaces return the same value, a buyer who checks out with Shop Pay Wallet first and logs in weeks later lands on one customer record.

***

## Next steps

[Sign in with Shop\
\
](https://shopify.dev/docs/api/shop/guides/use-cases/sign-in)

[Add the Shop SDK `login` feature to your self-hosted login page.](https://shopify.dev/docs/api/shop/guides/use-cases/sign-in)

[Create an app\
\
](https://shopify.dev/docs/api/shop/guides/creating-a-client)

[Set up a Shop app in the Dev Dashboard to get a client ID and client secret.](https://shopify.dev/docs/api/shop/guides/creating-a-client)

[GraphQL pre-payment\
\
](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment)

[Create and submit payment request sessions using the Storefront API.](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment)

***
