Hire Lovable Xperts
Integrations & APIs

The Lovable Shopify Integration: What Works and What Breaks

Connecting a Lovable app to Shopify works cleanly through the Storefront API, which is built for browser use, and breaks most often on the Admin API, webhooks, and CORS. The rule that saves you: read storefront data with a public Storefront token in the browser, but run every Admin API call and webhook handler server-side in an edge function so a secret token never reaches the client.

By Hire Lovable Xperts · Last verified: 2026-07-19

What actually works when you connect a Lovable app to Shopify?

Storefront reads work well from the browser; anything privileged must move to a server. Shopify's Storefront API is a GraphQL API explicitly designed for public, client-side use — product listings, collections, search, and cart — authenticated with a public Storefront access token. The Admin API (orders, inventory, fulfilment) uses a secret token that Shopify says must never appear in client-side code, so those calls belong in a Supabase Edge Function.

The single most useful mental model is a split by trust boundary. The Storefront API is meant to be exposed to shoppers, so a public access token in your Lovable front end is acceptable and the endpoint is CORS-friendly for browser calls. The Admin API is meant for back-office operations, so its access token is a secret; calling it from the browser both leaks that token and trips CORS. Get this split right and most Shopify integration pain disappears.

Shopify's own docs draw the line plainly: public Storefront tokens are rate-limited by customer IP and safe in the browser, while private Storefront tokens and Admin API tokens "should be treated as secret and not used on the client-side." A Lovable-generated integration that calls the Admin API directly from a React component is the version that demos and then fails — or worse, ships your secret token to every visitor.

Storefront API vs Admin API — Which One Your Lovable App Needs
TaskCorrect APIWhere it runsToken
List products / collectionsStorefront (GraphQL)Browser is finePublic Storefront access token
Search, build a cart, checkout URLStorefront (GraphQL)Browser is finePublic Storefront access token
Read or edit ordersAdmin (GraphQL)Edge Function onlyAdmin access token (secret)
Adjust inventory / fulfilmentAdmin (GraphQL)Edge Function onlyAdmin access token (secret)
React to a new orderWebhook (orders/create)Edge Function onlyHMAC-verified with app secret

Related: the Integrations & APIs hub · why a browser call to a keyed API gets CORS-blocked

Which Shopify API does my Lovable app actually need?

Choose by what the feature does, not by what is easiest to prompt. If you are showing a storefront to shoppers, use the Storefront API — it is GraphQL-only, browser-safe, and reachable at https://{store}.myshopify.com/api/{version}/graphql.json with the X-Shopify-Storefront-Access-Token header. If you are managing orders, inventory, or customers, use the Admin API from a server, at the /admin/api/{version}/graphql.json endpoint.

The Storefront API is GraphQL exclusively — Shopify states there is no REST storefront API — and it even supports limited tokenless access for basic product and cart queries. That makes it a natural fit for a Lovable front end: point a fetch at the GraphQL endpoint, send the public access token in the X-Shopify-Storefront-Access-Token header, and render the response.

The Admin API is the powerful, sensitive half. It authenticates with an access token passed in the X-Shopify-Access-Token header and is where you read and mutate orders, inventory, and customers. Shopify does offer a Direct API Access mode for embedded admin apps that call from the browser, but for a standalone Lovable app the safe default is to proxy every Admin call through an edge function.

Related: move the secret Admin token into an edge function

How do I connect the Shopify Storefront API to a Lovable app?

Create a Storefront access token in Shopify, then query the GraphQL endpoint from your Lovable front end with that token in the header. Because the Storefront API is designed for public use, this is one of the few keyed calls you can legitimately make from the browser — the public token is rate-limited by IP, not a secret. Keep every Admin API call out of this path.

  1. In your Shopify admin, install or create a custom app and enable Storefront API access to generate a public Storefront access token.
  2. In your Lovable app, POST your GraphQL query to https://YOUR-STORE.myshopify.com/api/2026-07/graphql.json (use the current API version).
  3. Send two headers: Content-Type: application/json and X-Shopify-Storefront-Access-Token set to your public token.
  4. Render products, collections, or cart data from the JSON response — no server round-trip is required for read-only storefront queries.
  5. For checkout, use the Storefront API's cart mutations to produce a checkout URL and redirect the shopper to Shopify's hosted checkout.
  6. Confirm on your live domain, not just the Lovable preview, that the requests return 200 and no Admin token appears anywhere in the browser.
A public Storefront access token is meant to be seen by shoppers — do not confuse it with the Admin API token. Only the Storefront public token belongs in front-end code. If you ever need order or inventory data on that same page, fetch it through an edge function instead of reaching for the Admin token in the browser.

Why do I get a CORS error calling the Shopify Admin API from the browser?

Because the browser's same-origin policy blocks it, and that block is protecting you from a bigger mistake. The Admin API is not meant for browser calls, so it does not return the Access-Control-Allow-Origin header your site needs — and even if it did, you would be shipping a secret Admin token to every visitor. The fix is to move the Admin call into a Supabase Edge Function.

This is the same class of problem covered in our CORS guide: a keyed, server-only API called from the front end. Server-to-server requests are not subject to the browser same-origin policy, so an edge function can call the Admin API normally and return only the data your UI needs. Your Admin token stays in an environment variable the browser never sees.

Treat any Admin token that has already appeared in client code as compromised. Rotate it in the Shopify admin, remove it from all front-end code and any VITE_ prefixed variable, and re-add it only as an edge function secret. A VITE_ variable is inlined into the public bundle by design, so it is never a safe home for a Shopify Admin token.

Shopify Integration Failure Field Guide
SymptomRoot causeCorrect fix
CORS error calling the Admin API from the browserAdmin API is server-only and returns no browser CORS headersProxy the call through a Supabase Edge Function
Storefront query returns 401 / 403Wrong or missing X-Shopify-Storefront-Access-Token, or Storefront access not enabledEnable Storefront API on the app and send the public token header
Admin token visible in the browser network tabSecret Admin token wired into front-end code or a VITE_ variableRotate the token, move it to an edge function secret
Webhook never triggers your handlerNo subscription created, or endpoint points at the preview URLSubscribe the topic to your deployed HTTPS endpoint
Webhook fires but is rejected as unverifiedHMAC not checked, or body parsed before verifyingVerify X-Shopify-Hmac-Sha256 against the raw body

Related: the full Lovable CORS fix with a proxy pattern · Lovable env & secrets best practices

How do I handle Shopify webhooks (like orders/create) in a Lovable app?

Subscribe to the webhook topic in Shopify, receive the delivery at a Supabase Edge Function, and verify the HMAC signature before trusting the payload. Shopify sends each event to a fixed HTTPS endpoint and signs it, so your handler must confirm the signature, respond quickly, and ignore duplicates. Never run this in the browser — webhooks are server-to-server by design.

Two failure modes dominate here, and both mirror the Stripe webhook problems elsewhere in this hub. First, the endpoint is registered against the ephemeral Lovable preview URL instead of your stable deployed domain, so Shopify has nowhere to deliver. Second, the handler parses the body before verifying, which changes the bytes and makes the HMAC never match — the same raw-body trap that breaks Stripe verification.

Shopify is explicit that webhook delivery is not guaranteed and events can be missed. For anything that must stay consistent — order counts, inventory, fulfilment state — pair the webhook with a periodic reconciliation job that re-reads the Admin API and corrects drift, rather than trusting the webhook as the only source of truth.

  1. Decide the topic you need (for example, orders/create) and subscribe to it via the shopify.app.toml config or the GraphQL Admin API, pointing the destination at your deployed edge function URL.
  2. In the edge function, read the raw request body with await req.text() — do not JSON.parse it first, because the signature is computed over the exact bytes.
  3. Compute an HMAC-SHA256 digest of that raw body using your app's secret and compare it, in constant time, to the X-Shopify-Hmac-Sha256 request header.
  4. If the signatures do not match, return a 401 and stop; if they match, parse the JSON and process the event.
  5. De-duplicate using the X-Shopify-Webhook-Id header so a redelivered event is not processed twice.
  6. Return a 200 quickly; do any slow work asynchronously so Shopify does not treat the delivery as failed and retry it.
Verify the HMAC before you act on a Shopify webhook. Without it, anyone who learns your endpoint URL can POST a forged orders/create event and trigger fulfilment or credit logic. Read the raw body, hash it with your app secret, and compare against X-Shopify-Hmac-Sha256 — an unverified handler is an open door.

Related: the raw-body verification trap, explained for Stripe

Why does my Shopify integration work in preview but break in production?

Because preview and your deployed app are separate environments with separate origins and secrets. A Storefront call that worked in the lovable.app preview can hit a CORS or token gap on your custom domain, and a webhook registered against the preview URL simply never fires in production. The Admin token you set in the editor may also be absent from the deployed edge function's environment.

This is the integrations case of the production gap: behaviour diverges once the app leaves the editor sandbox. Origin-specific CORS, an ephemeral preview URL that cannot be a stable webhook endpoint, and a vanished environment variable are the three usual culprits. Proxying Admin calls server-side removes the origin variable entirely, and registering your deployed domain as the webhook destination removes the URL variable.

Always confirm your secrets exist in the deployed environment, not only in the Lovable editor. A Shopify Admin token or app secret set in the editor sandbox does not automatically exist in the deployed edge function's runtime — set it explicitly there and redeploy, then verify against your live domain rather than assuming preview reflects production.

Related: why Lovable env vars vanish on deploy

When should I hand the Shopify integration to a senior engineer?

Hand it over when money or fulfilment depends on it and the fix is not obvious — a mis-verified webhook, an Admin token that may have leaked, or a checkout flow that must be reliable. Commerce integrations span three systems at once (Shopify, your edge functions, your database), and a silent gap there means orders that do not process or a token abused on your store account.

A specialist wires the Storefront reads to stay in the browser, moves every Admin call and webhook into signature-verified edge functions, adds idempotency and a reconciliation job so no order is missed, and rotates any token that was exposed. Productionizing this correctly once is far cheaper than debugging dropped orders after launch.

Do not iterate on commerce code with more Lovable prompts. Re-prompting a webhook or checkout handler risks stacking a second silent failure on the first — and on a Shopify integration that means real orders and real inventory, not just a demo that looked fine.

Related: productionize your Lovable + Shopify app · book a build review call

Frequently asked questions

Can I call the Shopify Storefront API directly from my Lovable front end?
Yes. The Storefront API is a GraphQL API explicitly designed for public, client-side use, authenticated with a public Storefront access token sent in the X-Shopify-Storefront-Access-Token header. That token is rate-limited by customer IP, not a secret, so shipping it in the browser is acceptable. Point your fetch at https://your-store.myshopify.com/api/{version}/graphql.json and render the response — no server round-trip is needed for storefront reads.
Why can't I call the Shopify Admin API from the browser?
Two reasons. First, the Admin API is server-oriented and does not return the CORS headers a browser needs, so the request is blocked. Second, and more important, the Admin token is a secret — Shopify says private and Admin tokens should be treated as secret and not used on the client-side. Calling the Admin API from a React component would ship that token to every visitor. Proxy Admin calls through a Supabase Edge Function instead.
What is the difference between the Storefront API and the Admin API?
The Storefront API is GraphQL-only and built for shoppers: products, collections, search, cart, and checkout, authenticated with a public token that is safe in the browser. The Admin API manages the back office — orders, inventory, customers, fulfilment — with a secret access token that must stay server-side. As a rule, storefront reads can run in the browser, while everything privileged runs in an edge function.
How do I verify a Shopify webhook in a Lovable edge function?
Read the raw request body with await req.text() before parsing, compute an HMAC-SHA256 digest of those exact bytes using your app's secret, and compare it against the X-Shopify-Hmac-Sha256 header. If they do not match, reject the request with a 401. Parsing the JSON first changes the bytes and breaks verification — the same raw-body trap that breaks Stripe webhooks. De-duplicate using the X-Shopify-Webhook-Id header.
My Shopify webhook does not fire — what is wrong?
Usually the subscription points at the ephemeral Lovable preview URL rather than your stable deployed domain, so Shopify has nowhere to deliver. Register the topic against your deployed edge function URL and confirm the delivery there, not in preview. Also remember Shopify does not guarantee delivery — for anything that must stay consistent, add a reconciliation job that re-reads the Admin API and corrects any drift.
It works in the Lovable preview but breaks on my live store — why?
Preview and production are separate environments with different origins and secrets. A Storefront call can hit a CORS or token gap on your custom domain, a webhook registered against the preview URL never fires in production, and an Admin token set only in the editor may be missing from the deployed edge function. Set secrets in the deployed environment, register your real domain as the webhook endpoint, and test on the live site.

Talk to a senior engineer — not a salesperson.

Book a free 30-minute audit call. We'll diagnose what's wrong and tell you exactly what it costs to fix.

Book a free audit call