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.
| Task | Correct API | Where it runs | Token |
|---|---|---|---|
| List products / collections | Storefront (GraphQL) | Browser is fine | Public Storefront access token |
| Search, build a cart, checkout URL | Storefront (GraphQL) | Browser is fine | Public Storefront access token |
| Read or edit orders | Admin (GraphQL) | Edge Function only | Admin access token (secret) |
| Adjust inventory / fulfilment | Admin (GraphQL) | Edge Function only | Admin access token (secret) |
| React to a new order | Webhook (orders/create) | Edge Function only | HMAC-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.
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.
- In your Shopify admin, install or create a custom app and enable Storefront API access to generate a public Storefront access token.
- In your Lovable app, POST your GraphQL query to https://YOUR-STORE.myshopify.com/api/2026-07/graphql.json (use the current API version).
- Send two headers: Content-Type: application/json and X-Shopify-Storefront-Access-Token set to your public token.
- Render products, collections, or cart data from the JSON response — no server round-trip is required for read-only storefront queries.
- For checkout, use the Storefront API's cart mutations to produce a checkout URL and redirect the shopper to Shopify's hosted checkout.
- Confirm on your live domain, not just the Lovable preview, that the requests return 200 and no Admin token appears anywhere 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.
| Symptom | Root cause | Correct fix |
|---|---|---|
| CORS error calling the Admin API from the browser | Admin API is server-only and returns no browser CORS headers | Proxy the call through a Supabase Edge Function |
| Storefront query returns 401 / 403 | Wrong or missing X-Shopify-Storefront-Access-Token, or Storefront access not enabled | Enable Storefront API on the app and send the public token header |
| Admin token visible in the browser network tab | Secret Admin token wired into front-end code or a VITE_ variable | Rotate the token, move it to an edge function secret |
| Webhook never triggers your handler | No subscription created, or endpoint points at the preview URL | Subscribe the topic to your deployed HTTPS endpoint |
| Webhook fires but is rejected as unverified | HMAC not checked, or body parsed before verifying | Verify 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.
- 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.
- 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.
- 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.
- If the signatures do not match, return a 401 and stop; if they match, parse the JSON and process the event.
- De-duplicate using the X-Shopify-Webhook-Id header so a redelivered event is not processed twice.
- Return a 200 quickly; do any slow work asynchronously so Shopify does not treat the delivery as failed and retry it.
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.
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?
Why can't I call the Shopify Admin API from the browser?
What is the difference between the Storefront API and the Admin API?
How do I verify a Shopify webhook in a Lovable edge function?
My Shopify webhook does not fire — what is wrong?
It works in the Lovable preview but breaks on my live store — why?
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.