Below is the flow of how I get access to the Storefront Access Token:
-
When the Shopify app is installed, storeSession() is called with the new session
-
The session contains the Admin Access Token (full permissions)
-
This Admin token is used to authenticate the GraphQL request
-
Use the Admin Access Token to make a GraphQL mutation: storefrontAccessTokenCreate
-
Returns a Storefront Access Token
import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma";
/**
* Minimal wrapper to capture access token when session is created
*/
export class TokenCaptureSessionStorage {
constructor(prisma) {
this.storage = new PrismaSessionStorage(prisma);
}
async storeSession(session) {
console.log("Shop:", session.shop);
console.log("Admin Access Token:", session.accessToken);
console.log("Session ID:", session.id);
// Create a Storefront Access Token for order attribution using GraphQL
if (session.accessToken) {
try {
const graphqlQuery = {
query: `
mutation StorefrontAccessTokenCreate($input: StorefrontAccessTokenInput!) {
storefrontAccessTokenCreate(input: $input) {
userErrors {
field
message
}
shop {
id
}
storefrontAccessToken {
accessScopes {
handle
}
accessToken
title
}
}
}
`,
variables: {
input: {
title: "Twillit Sales Attribution"
}
}
};
const response = await fetch(
`https://${session.shop}/admin/api/2025-01/graphql.json`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Shopify-Access-Token": session.accessToken,
},
body: JSON.stringify(graphqlQuery),
},
);
if (response.ok) {
const data = await response.json();
const result = data.data?.storefrontAccessTokenCreate;
if (result?.userErrors?.length > 0) {
console.error("GraphQL user errors:", result.userErrors);
} else if (result?.storefrontAccessToken) {
const storefrontToken = result.storefrontAccessToken.accessToken;
const accessScopes = result.storefrontAccessToken.accessScopes;
}
The cart permalink works perfectly fine without adding the access token as an additional parameter to the url. However, once I add it to the url, I get the following error page.
It would be greatly appreciated if someone can assist me with what I am doing wrong.
