Next.js: Dynamic OG Images + Short Links

~10–15 min

1) Add an OG image route

Create app/api/og/route.ts (App Router). This example renders a simple PNG using ImageResponse.

/* app/api/og/route.ts */
import { ImageResponse } from "next/og";

export const runtime = "edge";

export async function GET(req: Request) {
  const { searchParams } = new URL(req.url);
  const title = searchParams.get("title") || "My Product";
  return new ImageResponse(
    (
      <div
        style={{
          height: "100%",
          width: "100%",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          background: "white",
          fontSize: 64,
          fontWeight: 700,
          textAlign: "center",
          padding: 60
        }}
      >
        {title}
      </div>
    ),
    { width: 1200, height: 630 }
  );
}

2) Point a page’s OG image at that route

In a product page like app/products/[slug]/page.tsx:

/* app/products/[slug]/page.tsx */
type Props = { params: { slug: string } };

export async function generateMetadata({ params }: Props) {
  const product = await getProduct(params.slug); // your data layer
  const og = `https://yourdomain.com/api/og?title=${encodeURIComponent(product.name)}`;
  return {
    title: product.name,
    description: product.summary,
    openGraph: {
      title: product.name,
      description: product.summary,
      images: [{ url: og, width: 1200, height: 630, alt: product.name }]
    },
    twitter: { card: "summary_large_image" }
  };
}

export default async function Page({ params }: Props) {
  const product = await getProduct(params.slug);
  return (<main><h1>{product.name}</h1></main>);
}

3) (Optional) Use a short link per campaign

Create a short link that overrides OG for a campaign (you can rotate creatives later without redeploying Next.js):

# cURL example — adjust fields to your API
curl -X POST https://api.ogli.sh/link \
  -H "Authorization: Bearer $OGLI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourdomain.com/products/superwidget",
    "alias": "superwidget-launch",
    "og": {
      "title": "SuperWidget — Launch Day",
      "description": "Ships today. Free returns.",
      "image": "https://yourdomain.com/api/og?title=SuperWidget%20Launch"
    }
  }'

Share https://ogli.sh/superwidget-launch. To update the card after launch, swap the OG image or bump a querystring (e.g., ?v=2).

4) Testing & tips

Troubleshooting


← Back to all how-tos