Summary
So i am using Next.js 13 pages router, i want to implement a dynamic og:image on my meta tags. I created an API handler that generates the image from id
that i get from searchParams
.
It all worked flawlessly on my browser (see image-1), but when i deployed it to vercel, and tried to share the link or use Facebook’s Meta Debugger, it doesn’t show the values.
Code
This is my simplified implementation for both of the [id]/page.tsx:
// client
export default function Product() {
const router = useRouter();
const { id } = router.query;
const { property, isLoading } = useProperty(Number(id));
const title = property ? `${NAME} | ${property.name_formatted}` : `${NAME}`;
const description = property ? property.description : "Empty property description";
const currentUrl = `${BASE_URL}/api/og?id=${id}`;
return (
<>
<NextSeo
title={title}
description={description}
openGraph={{
title,
description,
images: [
{
url: currentUrl,
width: 1200,
height: 630,
alt: title,
},
],
siteName: NAME,
}}
/>
{/* Additional Codes */}
</>
);
}
And for /api/og.tsx:
// api handler
import { ImageResponse } from "@vercel/og";
import { NextRequest } from "next/server";
export const config = { runtime: "edge" };
async function fetchProperty(id) {
const response = await fetch(`${BASE_API_URL}/properties/${id}`);
return response.json();
}
export default async function handler(req: NextRequest) {
const id = req.nextUrl.searchParams.get("id");
if (!id) return new Response("Missing ID", { status: 400 });
const property = await fetchProperty(id);
if (!property) return new Response("Property not found", { status: 404 });
return new ImageResponse(
<div style={{ display: "flex", flexDirection: "column", padding: "24px" }}>
<h1>{property.name}</h1>
<img src={property.imageUrl} alt={property.name} />
</div>,
{ width: 1200, height: 630 }
);
}
What I’ve Tried
I implemented next-seo but it didn’t work, I think it’s because of the [id]/page.tsx being a client-side file, the og:image is only loaded on the browser instead of the server