Shopify Integration
How the template maps to Shopify concepts - menus, products, collections, and cache invalidation via webhooks.
The template connects to Shopify through the Storefront API. This page covers the Shopify-side configuration that the template expects after your storefront token and permissions are in place - concept mapping, required menus, and cache invalidation.
For token setup and required scopes, see Getting Started and Storefront API Permissions.
For the API client and query patterns, see Storefront API.
Concept mapping
| Shopify concept | Template route | What renders it |
|---|---|---|
| Products | /products/[handle] | Product detail page with variants, gallery, buy section |
| Collections | /collections/[handle] | Product grid with filtering, sorting, pagination |
| Menus | Navigation, footer | Megamenu, quick links bar, footer columns |
| Pages | /pages/[slug] | Marketing page renderer (requires CMS setup) |
| Search | /search | Same grid as collections, driven by query param |
| Cart | /cart + overlay | Cart context with optimistic updates |
Required menus
By default, the template uses hardcoded navigation links and an empty footer. Use /vercel-shop:enable-shopify-menus to replace them with dynamic menus fetched from Shopify.
When enabled, the template fetches menus by handle from Online Store → Navigation in Shopify admin. Common handles:
| Menu handle | Where it renders | Structure |
|---|---|---|
main-menu | Top navigation links (or megamenu) | Flat list or 3-level hierarchy |
footer | Footer link columns | 2-level: column headings → links |
Menu items can link to collections, products, pages, or custom URLs.
Webhooks and cache invalidation
All read operations are cached with "use cache" and cacheLife("max"). Without webhooks, changes in Shopify won't appear until the cache expires. To get near-instant updates, configure Shopify webhooks to hit the template's invalidation endpoint.
Webhook endpoint
The handler verifies the HMAC signature using the SHOPIFY_WEBHOOK_SECRET environment variable, then calls revalidateTag() for the affected cache tags.
Supported topics
| Webhook topic | Cache tags invalidated |
|---|---|
products/create | products, collections, product-{handle}, recommendations-{handle} |
products/update | products, collections, product-{handle}, recommendations-{handle} |
products/delete | products, collections, product-{handle}, recommendations-{handle} |
collections/create | collections, products, menus, collection-{handle} |
collections/update | collections, products, menus, collection-{handle} |
collections/delete | collections, products, menus |
inventory_levels/* | products, collections |
metaobjects/* | cms:all + type-specific tags (if using Shopify CMS) |
Setting up webhooks
In your Shopify admin, go to Settings → Notifications → Webhooks:
- Set the webhook URL to
https://your-domain.com/api/webhooks/shopify - Select JSON as the format
- Create webhooks for each topic in the table above
- Copy the webhook signing secret and add it to your environment:
Important: Without
SHOPIFY_WEBHOOK_SECRET, the handler skips signature verification. Always set this in production.
How it works
When Shopify sends a webhook, the handler:
- Verifies the HMAC-SHA256 signature using
crypto.timingSafeEqual - Parses the topic header to determine what changed
- Extracts the product/collection handle from the payload for targeted invalidation
- Calls
revalidateTag()for each affected cache tag - Returns the list of invalidated tags for logging
This means a product update in Shopify invalidates only that product's cache and its recommendations - not every page on the site.
Key files
| File | Purpose |
|---|---|
app/api/webhooks/shopify/route.ts | Webhook handler with HMAC verification |
lib/shopify/operations/menu.ts | Menu fetching by handle (used after enable-shopify-menus skill) |
lib/shopify/client.ts | Core Storefront API client |