Issue: Hi, I'm trying to activate a Shopify web pixel extension on a production store. The web pixel extension is configured in the Shopify Remix app template. The backend is wired to Express.js. What I've tried: Approach_1: I was able to activate it on the dev/test store using the Shopify app dev GraphQL by following this guide https://shopify.dev/docs/apps/build/marketing-analytics/build-web-pixels#:~:text=To%20activate%20a%20web%20pixel,extension. However, I couldn't apply it on the production store since i cannot run shopify app dev on production store to open up the shopify GraphQL console. mutation { # This mutation creates a web pixel, and sets the `accountID` declared in `shopify.extension.toml` to the value `123`. webPixelCreate(webPixel: { settings: "{\"accountID\":\"123\"}" }) { userErrors { code field message } webPixel { settings id } } } Approach_2: I've also tried this guide that activates the pixel using shopify remix app's loader function. Unfortunately it didn't work as well. https://community.shopify.com/c/extensions/how-do-you-actually-activate-the-web-pixel/m-p/2496617 shopify remix app template > app app._index.jsx export const loader = async ({ request }) => { // Authenticate with Shopify const { admin } = await authenticate.admin(request); const mutationResponse = await admin.graphql( #graphql mutation webPixelCreate($webPixel: WebPixelInput!) { webPixelCreate(webPixel: $webPixel) { userErrors { field message } webPixel { settings id } } } , { variables: { webPixel: { settings: { "accountID": 'Account_ID_45466_this_is_as_per_toml' }, }, }, } ); if (!mutationResponse.ok) { console.error('Request failed', mutationResponse); return; } const data = await mutationResponse.json(); console.log(data); return mutationResponse; }; const loaderDataForWebPixel = useLoaderData(); Approach_3: Oauth redirect and Token Exchange on Express.js endpoint routes>shopifyRouter.js file import { shopify } from '../shopifyApi.js'; import { Router } from 'express'; import dotenv from 'dotenv'; import { shopify, RequestedTokenType } from '../shopifyApi.js'; import cookieParser from 'cookie-parser'; import axios from 'axios'; dotenv.config(); const router = Router(); // Middleware to set CSP headers for embedded apps const setCSPHeaders = (req, res, next) => { const shop = req.query.shop; const shopDomain = shop ? `https://${shop}` : null; const shopifyAdminDomain = "https://admin.shopify.com"; if (shopDomain) { res.setHeader("Content-Security-Policy", `frame-ancestors ${shopDomain} ${shopifyAdminDomain}`); } else { res.setHeader("Content-Security-Policy", `frame-ancestors ${shopifyAdminDomain}`); } next(); }; router.use((req, res, next) => { console.log(`Incoming request: ${req.method} ${req.url}`); next(); }); // Apply middleware router.use(cookieParser()); router.use(setCSPHeaders); // Route to handle the initial OAuth router.get('/install', async (req, res) => { try { const shop = req.query.shop; if (!shop) { return res.status(400).json({ error: 'Missing "shop" query parameter' }); } await shopify.auth.begin({ shop, callbackPath: '/auth/callback', isOnline: false, rawRequest: req, rawResponse: res, }); } catch (error) { console.error('Error during install:', error.message); console.error('Stack trace:', error.stack); res.status(500).json({ error: 'Error during install', message: error.message }); } }); // Route to handle the OAuth callback and activate web pixel router.get('/auth/callback', async (req, res) => { try { const callbackResponse = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); const { session } = callbackResponse; const accessToken = session.accessToken; // Activate web pixel const graphqlUrl = `https://${session.shop}/admin/api/2023-07/graphql.json`; const graphqlHeaders = { 'Content-Type': 'application/json', 'X-Shopify-Access-Token': accessToken, }; const graphqlMutation = { query: ` mutation { webPixelCreate(webPixel: { settings: "{\\"accountID\\":\\"88888888\\"}" }) { userErrors { code field message } webPixel { settings id } } } `, }; const graphqlResponse = await axios.post(graphqlUrl, graphqlMutation, { headers: graphqlHeaders }); if (graphqlResponse.data.errors) { console.error('GraphQL errors:', graphqlResponse.data.errors); return res.status(500).json({ error: graphqlResponse.data.errors }); } console.log('Web pixel activated:', graphqlResponse.data.data); res.json(graphqlResponse.data.data); } catch (error) { console.error('Error during OAuth callback:', error.message); console.error('Stack trace:', error.stack); res.status(500).json({ error: 'Error during OAuth callback', message: error.message }); } }); // Route get access token and activate web pixel router.get('/auth', async (req, res) => { try { const shop = shopify.utils.sanitizeShop(req.query.shop, true); const headerSessionToken = getSessionTokenHeader(req); const searchParamSessionToken = getSessionTokenFromUrlParam(req); const sessionToken = headerSessionToken || searchParamSessionToken; if (!sessionToken) { return res.status(400).json({ error: 'Missing session token' }); } const session = await shopify.auth.tokenExchange({ sessionToken, shop, requestedTokenType: RequestedTokenType.OfflineAccessToken, // or RequestedTokenType.OnlineAccessToken }); // Activate web pixel const accessToken = session.accessToken; console.log("🚀 ~ file: shopifyRouter.js:132 ~ router.get ~ accessToken:", accessToken); const graphqlUrl = `https://${shop}/admin/api/2023-07/graphql.json`; const graphqlHeaders = { 'Content-Type': 'application/json', 'X-Shopify-Access-Token': accessToken, }; const graphqlMutation = { query: ` mutation { webPixelCreate(webPixel: { settings: "{\\"accountID\\":\\"88888888\\"}" }) { userErrors { code field message } webPixel { settings id } } } `, }; const graphqlResponse = await axios.post(graphqlUrl, graphqlMutation, { headers: graphqlHeaders }); if (graphqlResponse.data.errors) { console.error('GraphQL errors:', graphqlResponse.data.errors); return res.status(500).json({ error: graphqlResponse.data.errors }); } console.log('Web pixel activated:', graphqlResponse.data.data); res.json(graphqlResponse.data.data); } catch (error) { console.error('Error during token exchange:', error.message); console.error('Stack trace:', error.stack); res.status(500).json({ error: 'Error during token exchange', message: error.message }); } }); // Helper functions to get session token function getSessionTokenHeader(request) { const authHeader = request.headers.authorization; if (authHeader && authHeader.startsWith('Bearer ')) { return authHeader.substring(7); } return null; } function getSessionTokenFromUrlParam(request) { return request.query.id_token || null; } export default router; shopifyApi.js file import '@shopify/shopify-api/adapters/node'; import { shopifyApi, LATEST_API_VERSION, RequestedTokenType } from '@shopify/shopify-api'; import dotenv from 'dotenv'; dotenv.config(); const myAppsLogFunction = (severity, message) => { console.log(`[${severity}] ${message}`); }; let shopify; try { shopify = shopifyApi({ apiKey: process.env.SHOPIFY_API_KEY, apiSecretKey: process.env.SHOPIFY_API_SECRET, scopes: ['read_products', 'write_products', 'read_customer_events', 'write_pixels'], hostName: process.env.SHOPIFY_APP_HOST, hostScheme: 'https', apiVersion: LATEST_API_VERSION, isEmbeddedApp: true, isCustomStoreApp: false, userAgentPrefix: 'Custom prefix', logger: { log: (severity, message) => { myAppsLogFunction(severity, message); }, level: 'info', httpRequests: true, timestamps: true, }, future: { unstable_newEmbeddedAuthStrategy: true, } }); } catch (error) { console.log('shopifyApi.js error', error); } export { shopify, RequestedTokenType }; Here are the approach_3 's results express-url-endpoint/install results to: { "error": "Error during Oauth callback", "message": Cannot complete Oauth process. Could not find an Oauth cookie for shop url: the-shop.myshopify.com" } express-url-endpoint/auth token exchange results to: { "error:": "Error during token exchange", "message": "Request failed with status code 401" }