Skip to main content

createCustomerAccountClient

The createCustomerAccountClient function creates a GraphQL client for querying the Customer Account API. It also provides methods to authenticate and check if the user is logged in.

Anchor to createcustomeraccountclient(options)createCustomerAccountClient(options)

Anchor to customerAccountId
customerAccountId
string
required

Unique UUID prefixed with shp_ associated with the application, this should be visible in the customer account api settings in the Hydrogen admin channel. Mock.shop doesn't automatically supply customerAccountId. Use npx shopify hydrogen env pull to link your store credentials.

Anchor to request
request
required

The object for the current Request. It should be provided by your platform.

Anchor to session
session
HydrogenSession
required

The client requires a session to persist the auth and refresh token. By default Hydrogen ships with cookie session storage, but you can use another session storage implementation.

Anchor to shopId
shopId
string
required

The shop id. Mock.shop doesn't automatically supply shopId. Use npx shopify hydrogen env pull to link your store credentials

Anchor to authorizePath
authorizePath
string

The oauth authorize path. Defaults to /account/authorize.

Anchor to authUrl
authUrl
string

This is the route in your app that authorizes the customer after logging in. Make sure to call customer.authorize() within the loader on this route. It defaults to /account/authorize.

Anchor to customAuthStatusHandler
customAuthStatusHandler
() =>

Use this method to overwrite the default logged-out redirect behavior. The default handler throws a redirect to /account/login with current path as return_to query param.

Anchor to customerApiVersion
customerApiVersion
string

Override the version of the API

Anchor to defaultRedirectPath
defaultRedirectPath
string

The path to redirect to after login. Defaults to /account.

Anchor to language
language
LanguageCode

Localization data.

Anchor to logErrors
logErrors
boolean | ((error?: Error) => boolean)

Whether it should print GraphQL errors automatically. Defaults to true

Anchor to loginPath
loginPath
string

The path to login. Defaults to /account/login.

Anchor to unstableB2b
unstableB2b
boolean

Deprecated. unstableB2b is now stable. Please remove.

Anchor to waitUntil
waitUntil
WaitUntil

The waitUntil function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform.

Anchor to authorize
authorize
() => Promise<Response>

On successful login, the customer redirects back to your app. This function validates the OAuth response and exchanges the authorization code for an access token and refresh token. It also persists the tokens on your session. This function should be called and returned from the Remix loader configured as the redirect URI within the Customer Account API settings in admin.

Anchor to getAccessToken
getAccessToken
() => Promise<string>

Returns CustomerAccessToken if the customer is logged in. It also run a expiry check and does a token refresh if needed.

Anchor to getApiUrl
getApiUrl
() => string

Creates the fully-qualified URL to your store's GraphQL endpoint.

Anchor to handleAuthStatus
handleAuthStatus
() => void |

Check for a not logged in customer and redirect customer to login page. The redirect can be overwritten with customAuthStatusHandler option.

Anchor to isLoggedIn
isLoggedIn
() => Promise<boolean>

Returns if the customer is logged in. It also checks if the access token is expired and refreshes it if needed.

Anchor to login
login
(options?: ) => Promise<Response>

Start the OAuth login flow. This function should be called and returned from a Remix action. It redirects the customer to a Shopify login domain. It also defined the final path the customer lands on at the end of the oAuth flow with the value of the return_to query param. (This is automatically setup unless customAuthStatusHandler option is in use)

Anchor to logout
logout
(options?: ) => Promise<Response>

Logout the customer by clearing the session and redirecting to the login domain. It should be called and returned from a Remix action. The path app should redirect to after logout can be setup in Customer Account API settings in admin.

Anchor to mutate
mutate
<TData = any>(mutation: string, options: ) => Promise<TData>

Execute a GraphQL mutation against the Customer Account API. This method execute handleAuthStatus() ahead of mutation.

Anchor to query
query
<TData = any>(query: string, options: ) => Promise<TData>

Execute a GraphQL query against the Customer Account API. This method execute handleAuthStatus() ahead of query.

Examples
import {
createCustomerAccountClient,
createRequestHandler,
} from '@shopify/hydrogen';
import {createCookieSessionStorage} from 'react-router';
import * as reactRouterBuild from 'virtual:react-router/server-build';

export default {
async fetch(request, env, executionContext) {
const session = await AppSession.init(request, [env.SESSION_SECRET]);

/* Create a Customer API client with your credentials and options */
const customerAccount = createCustomerAccountClient({
/* Runtime utility in serverless environments */
waitUntil: (p) => executionContext.waitUntil(p),
/* Public Customer Account API token for your store */
customerAccountId: env.PUBLIC_CUSTOMER_ACCOUNT_ID,
/* Shop Id */
shopId: env.SHOP_ID,
request,
session,
});

const handleRequest = createRequestHandler({
build: reactRouterBuild,
mode: process.env.NODE_ENV,
/* Inject the customer account client in the Remix context */
getLoadContext: () => ({customerAccount}),
});

const response = await handleRequest(request);

if (session.isPending) {
response.headers.set('Set-Cookie', await session.commit());
}

return response;
},
};

class AppSession {
isPending = false;

static async init(request, secrets) {
const storage = createCookieSessionStorage({
cookie: {
name: 'session',
httpOnly: true,
path: '/',
sameSite: 'lax',
secrets,
},
});

const session = await storage.getSession(request.headers.get('Cookie'));

return new this(storage, session);
}

get(key) {
return this.session.get(key);
}

destroy() {
return this.sessionStorage.destroySession(this.session);
}

flash(key, value) {
this.session.flash(key, value);
}

unset(key) {
this.isPending = true;
this.session.unset(key);
}

set(key, value) {
this.isPending = true;
this.session.set(key, value);
}

commit() {
this.isPending = false;
return this.sessionStorage.commitSession(this.session);
}
}
Was this page helpful?