Connect a Shopify store
import { Aside, Steps, Tabs, TabItem } from ‘@astrojs/starlight/components’;
Connecting Shopify enables a Website to have a real product catalog, cart, and checkout, plus optional sales channels (TikTok, Meta, Pinterest, Google, Marketplace Connect).
Prerequisites
Section titled “Prerequisites”- A Vantage Website with
status: "active" - A Shopify store URL (either an existing merchant store or a Shopify Partner dev store)
- The merchant logged in to Shopify in the same browser session
What gets created
Section titled “What gets created”When the OAuth flow completes, Vantage creates:
- A
commerceservice row with the store id + scopes - A Secrets Manager entry holding the Admin API access token
- A Storefront access token (public, read-only) on
metadata.storefrontAccessToken— what the template uses - Webhook subscriptions for
APP_UNINSTALLED+ GDPR compliance topics - A node on the Blueprint canvas
If the merchant already has channel apps installed (TikTok, Meta, etc.), those auto-populate as separate channel rows on the same Website.
-
Open the Website in the portal.
Go to
https://vantageconnections.dev/admin/websites/<websiteId>. You’ll see the Blueprint canvas. -
Drag the Commerce node from the picker onto the canvas.
The drawer opens on the right. It asks for the merchant’s Shopify subdomain.
-
Enter the store’s
myshopify.comsubdomain.For
acme.myshopify.com, typeacme. (Pasting the full URL also works — Vantage strips the tail.) -
Click Connect.
Vantage signs an HMAC state token and redirects you to Shopify’s OAuth screen.
-
Approve the app’s scopes on Shopify.
The merchant sees the scope list (read/write products, orders, inventory, customers, themes, publications). Click Install app.
-
Shopify redirects back to Vantage.
The callback (
/oauth/shopify/callback) verifies the state HMAC, exchanges the auth code for an access token, stores it in Secrets Manager, creates the commerce row, mints a Storefront token, and registers the webhook subscriptions. -
You land back on the Blueprint with the Commerce node live.
Status should be green. Click the node — the drawer shows the store domain, scopes granted, and a button to disconnect.
-
Channel apps auto-detect.
If the merchant has TikTok / Meta / Pinterest / Google / Marketplace Connect installed in their Shopify, you’ll see a row per channel appear within ~10 seconds (the Blueprint polls Shopify’s Publications API on mount + OAuth-callback).
How the template reads products
Section titled “How the template reads products”The Vantage website-template reads products via Shopify’s Storefront
API — not the Admin API:
import { createStorefrontClient } from "@shopify/hydrogen-react";
export const storefront = createStorefrontClient({ storeDomain: process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN!, storefrontApiVersion: "2026-04", publicStorefrontToken: process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_TOKEN!,});Both env vars are seeded into the Vercel project automatically when the commerce row is created — you don’t set them by hand.
Product pages are statically generated with ISR (revalidate: 60), so
adding a product in Shopify Admin shows up on the site within a minute.
How checkout works
Section titled “How checkout works”Today checkout is Shopify-hosted. The template’s BuyNow button redirects to a Shopify checkout URL:
"use client";import { useState } from "react";
export function BuyNow({ variantId }: { variantId: string }) { const [loading, setLoading] = useState(false); // bfcache fix: reset on pageshow // ... async function handleClick() { setLoading(true); const res = await fetch("/api/checkout", { method: "POST", body: JSON.stringify({ variantId }) }); const { url } = await res.json(); window.location.href = url; } return <button onClick={handleClick}>{loading ? "Opening checkout…" : "Buy now"}</button>;}Guest checkout is enabled by default — buyers don’t need a Shopify account.
Reading commerce state programmatically
Section titled “Reading commerce state programmatically”const { services } = await vc.websites.services("wb_01J7...");const commerce = services.find(s => s.serviceType === "commerce");const channels = services.filter(s => s.serviceType.startsWith("channel_"));
console.log("Store:", commerce?.externalId);console.log("Channels installed:", channels.map(c => c.serviceType));Disconnecting
Section titled “Disconnecting”From the portal: click the Commerce node, then Disconnect in the drawer. This:
- Calls Shopify to uninstall the Vantage Manager app
- Triggers Shopify’s
APP_UNINSTALLEDwebhook - Vantage’s webhook worker removes the commerce row + all dependent channel rows
- Revokes the Admin API token in Secrets Manager
The Website itself stays — only commerce-related services are removed.
Troubleshooting
Section titled “Troubleshooting”?shopify=error&reason=connect_failed in the URL after OAuth.
The OAuth callback failed. Most common cause is a missing
vantage/oauth/state-secret in Secrets Manager (only the platform
operator can fix — check the API Lambda logs). If you’re the operator,
create it with aws secretsmanager create-secret.
Channel apps don’t show up. Channels poll on Blueprint mount. Refresh the page. If still missing, the merchant’s Shopify likely doesn’t have the channel app installed — they can install it from Shopify’s app store.
See also
Section titled “See also”- Concepts → Commerce + channels — the data model
- Webhooks — Shopify HMAC contract + payload shapes