Skip to content

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).

  • 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

When the OAuth flow completes, Vantage creates:

  • A commerce service 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.

  1. Open the Website in the portal.

    Go to https://vantageconnections.dev/admin/websites/<websiteId>. You’ll see the Blueprint canvas.

  2. Drag the Commerce node from the picker onto the canvas.

    The drawer opens on the right. It asks for the merchant’s Shopify subdomain.

  3. Enter the store’s myshopify.com subdomain.

    For acme.myshopify.com, type acme. (Pasting the full URL also works — Vantage strips the tail.)

  4. Click Connect.

    Vantage signs an HMAC state token and redirects you to Shopify’s OAuth screen.

  5. Approve the app’s scopes on Shopify.

    The merchant sees the scope list (read/write products, orders, inventory, customers, themes, publications). Click Install app.

  6. 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.

  7. 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.

  8. 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).

The Vantage website-template reads products via Shopify’s Storefront API — not the Admin API:

templates/website/lib/shopify.ts
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.

Today checkout is Shopify-hosted. The template’s BuyNow button redirects to a Shopify checkout URL:

templates/website/app/components/BuyNow.tsx
"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.

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));

From the portal: click the Commerce node, then Disconnect in the drawer. This:

  1. Calls Shopify to uninstall the Vantage Manager app
  2. Triggers Shopify’s APP_UNINSTALLED webhook
  3. Vantage’s webhook worker removes the commerce row + all dependent channel rows
  4. Revokes the Admin API token in Secrets Manager

The Website itself stays — only commerce-related services are removed.

?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.