Shopify App Proxy with Next.js: Safe Data Display

April 4, 2026

Building a high-performance Shopify custom app in 2026 often means using Next.js. But when you need to display dynamic, external data directly on the storefront—data that might be sensitive or require complex backend logic—you run into the "CORS Wall" or the "Security Gap."

The solution is the Shopify App Proxy. This feature allows your app to "tunnel" requests through the Shopify domain (e.g.,

your-store.myshopify.com/apps/my-proxy
), making them appear as if they are coming from Shopify itself.

As a senior Shopify developer, here is the technical breakdown of how to build a secure App Proxy using Next.js.

1. What is an App Proxy and Why Use It?

Normally, if your storefront JavaScript (Liquid/Theme code) tries to fetch data from your

myapp.com/api/data
endpoint, the browser will block it due to CORS (Cross-Origin Resource Sharing) policies.

An App Proxy solves this by:

  1. Bypassing CORS: The request is made to your shop's own domain.
  2. Injecting Liquid: You can actually return Liquid code from your Next.js server, and Shopify will render it before it hits the customer's browser.
  3. Authentication: Shopify signs every request to your proxy with an HMAC, allowing your backend to verify that the request is legitimate and comes from a specific store.

2. Setting Up the Proxy in the Shopify Partners Dashboard

In your app settings:

  • Subpath Prefix: Choose
    apps
    ,
    a
    , or
    community
    .
  • Subpath: Choose a unique name (e.g.,
    my-custom-data
    ).
  • Proxy URL: The full URL to your Next.js API route (e.g.,
    https://myapp.com/api/proxy
    ).

3. Next.js Implementation: Verifying the HMAC

This is the most critical security step. Never trust a request to your proxy without verifying the signature.

// app/api/proxy/route.ts
import crypto from 'crypto';
import { NextResponse } from 'next/server';

export async function GET(req: Request) {
  const url = new URL(req.url);
  const queryParams = Object.fromEntries(url.searchParams.entries());
  
  const signature = queryParams.signature;
  const sharedSecret = process.env.SHOPIFY_API_SECRET;

  // 1. Remove signature and other internal keys
  const { signature: _, ...params } = queryParams;
  
  // 2. Sort keys alphabetically
  const sortedKeys = Object.keys(params).sort();
  const message = sortedKeys
    .map((key) => `${key}=${params[key]}`)
    .join('');

  // 3. Generate HMAC
  const generatedHmac = crypto
    .createHmac('sha256', sharedSecret)
    .update(message)
    .digest('hex');

  // 4. Verify
  if (signature !== generatedHmac) {
    return new NextResponse('Unauthorized', { status: 401 });
  }

  // Request is valid! Fetch your external data here
  const externalData = await fetchMyExternalDatabase();

  return NextResponse.json(externalData);
}

4. Fetching Data on the Storefront

In your Shopify Liquid theme or custom section, you can now fetch this data simply:

fetch('/apps/my-custom-data/api/proxy')
  .then(response => response.json())
  .then(data => {
    console.log("Secure external data:", data);
    // Update your DOM here
  });

Because the request is to

/apps/...
, it bypasses CORS and includes the customer's Shopify session data automatically if they are logged in.

5. Returning Liquid (The Ninja Move)

One of the most powerful features of the App Proxy is its ability to return Liquid. If you set the

Content-Type
header to
application/liquid
, Shopify will parse the response before displaying it.

return new Response(
  `<div>Hello, {{ customer.first_name }}! Here is your private data: ${data.value}</div>`, 
  {
    headers: { 'Content-Type': 'application/liquid' }
  }
);

This allows you to build deeply integrated experiences without needing a complex React frontend on the storefront.

6. Common Pitfalls to Avoid

  • Caching: Shopify can cache App Proxy responses. If you are returning real-time data, ensure your
    Cache-Control
    headers are set to
    no-cache
    .
  • Large Payloads: Proxies have a timeout (usually 5-10 seconds). If your backend takes too long to process data, the request will fail.
  • POST Requests: While supported, POST requests to Proxies are more complex to verify and should be used with caution for state-changing operations.

Summary: The Ultimate Storefront Tool

The Shopify App Proxy is the bridge between the standardized Shopify world and your custom, external data environment. By combining it with a modern Next.js backend, you can build secure, high-performance features that feel native to the Shopify experience.

Are you building a complex Shopify app or need to integrate custom external data into your storefront? Let’s talk about how to architect a secure App Proxy for your project.


Related Articles