How to Generate OG Images Dynamically with an API
Every link you share has an Open Graph image. Some look great. Most look like afterthoughts—generic logos or blank previews that blend into the social feed.
The difference? Dynamic generation.
Sites that generate OG images dynamically create unique visuals for every page. Blog posts get images with the actual title. Product pages show the product. Landing pages display the headline that matters.
Here's how to set it up for your site.
What are og images and why they matterWhat Are OG Images and Why They Matter
Open Graph images are the preview thumbnails that appear when you share a link on Twitter, LinkedIn, Facebook, Slack, or iMessage. They're controlled by a meta tag in your HTML:
<meta property="og:image" content="https://yoursite.com/images/preview.png" />The problem? Most sites use one generic image for everything. Or worse, they don't use anything at all.
Why dynamic OG images work:
- 40% higher click-through rates on shared links (based on Twitter's own research)
- Brand recognition in crowded feeds
- Each page becomes share-ready without manual design
- Professional appearance that builds trust
If you publish content regularly, manual OG image creation doesn't scale. You'll burn hours on repetitive work that an API handles instantly.
The architecture how it worksThe Architecture: How It Works
Dynamic OG generation follows this pattern:
Page Loads → Extract Title/Data → Call Image API → Return Image URL → Serve as OG Tag
You have two timing options:
Build time generationBuild Time Generation
Generate images when your site builds. Best for static sites and blogs where content doesn't change after publish.
Pros: Fast page loads, no API calls on visit Cons: Rebuilds needed for updates, higher build times
Runtime generationRuntime Generation
Generate images on-demand when the OG image URL is requested. Best for dynamic content and large sites.
Pros: Always current, no build dependency Cons: First request slightly slower, requires caching
For most sites, build time works better. Runtime makes sense when you have thousands of pages or frequently changing content.
Method 1 nextjs with api routesMethod 1: Next.js with API Routes
Next.js makes this straightforward with API routes that generate images on request.
Step 1 create the api routeStep 1: Create the API Route
Create a file at app/api/og/route.ts (App Router) or pages/api/og.ts (Pages Router):
// app/api/og/route.ts
import { NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const title = searchParams.get('title') || 'Default Title';
// Call Imejis.io API
const response = await fetch(
`https://render.imejis.io/v1/your-og-template-id`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.IMEJIS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ title }),
}
);
const data = await response.json();
// Redirect to the generated image
return Response.redirect(data.url, 302);
}Step 2 add the meta tagStep 2: Add the Meta Tag
In your page component:
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
const post = await getPost(params.slug);
return {
openGraph: {
images: [{
url: `/api/og?title=${encodeURIComponent(post.title)}`,
width: 1200,
height: 630,
}],
},
};
}Now every blog post gets a unique OG image with its title.
Step 3 add cachingStep 3: Add Caching
Generating the same image repeatedly wastes API calls. Add caching:
// Add to your API route
export const revalidate = 86400; // Cache for 24 hoursOr use a more sophisticated caching strategy with Redis or your CDN's edge caching.
Method 2 static site generatorsMethod 2: Static Site Generators
For Astro, Hugo, Eleventy, or other static generators, generate images at build time.
Astro exampleAstro Example
// src/pages/og/[...slug].png.ts
import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { title: post.data.title },
}));
}
export const GET: APIRoute = async ({ props }) => {
const response = await fetch(
'https://render.imejis.io/v1/your-og-template-id',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${import.meta.env.IMEJIS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ title: props.title }),
}
);
const data = await response.json();
const imageResponse = await fetch(data.url);
return new Response(await imageResponse.arrayBuffer(), {
headers: { 'Content-Type': 'image/png' },
});
};The image generates during build and gets served as a static file.
Method 3 headless cms integrationMethod 3: Headless CMS Integration
If your content lives in a CMS like Contentful, Sanity, or Strapi, trigger image generation when content publishes.
Webhook approachWebhook Approach
- Set up a webhook that fires on content publish
- Webhook calls your image generation endpoint
- Generated image URL saves back to the CMS
- Your site reads the URL from the CMS
// Webhook handler (Vercel Function, AWS Lambda, etc.)
export async function handleContentPublish(content) {
// Generate the OG image
const response = await fetch(
'https://render.imejis.io/v1/your-og-template-id',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.IMEJIS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: content.title,
author: content.author,
category: content.category,
}),
}
);
const { url } = await response.json();
// Save URL back to CMS
await updateContentInCMS(content.id, { ogImage: url });
}This approach pre-generates images so page loads stay fast. Learn more about automating social media images with similar workflows.
Designing your og templateDesigning Your OG Template
A good OG template includes:
Required elements:
- Title text (dynamic, editable via API)
- Your logo or brand mark (static)
- Background that works at any size
Optional elements:
- Author name or avatar
- Category or tag
- Reading time
- Publish date
Design specificationsDesign Specifications
OG images display at different sizes across platforms:
| Platform | Display Size | Recommended |
|---|---|---|
| 800x418px | 1200x628px | |
| 1200x630px | 1200x630px | |
| 1200x627px | 1200x628px | |
| Slack | 500x250px | 1200x628px |
Always create at 1200x630px. It's the standard that works everywhere. Check our template library for OG-specific designs.
Text handlingText Handling
Long titles break layouts. Build your template to handle:
- Short titles (3-5 words)
- Medium titles (8-12 words)
- Long titles (15+ words with truncation)
Test with your longest realistic headline before deploying.
Common issues and fixesCommon Issues and Fixes
Images not updatingImages Not Updating
Social platforms cache OG images aggressively. To force refresh:
- Twitter: Use the Card Validator
- Facebook: Use the Sharing Debugger
- LinkedIn: Add
?v=2to your image URL to bust cache
Wrong image dimensionsWrong Image Dimensions
If images appear cropped or distorted, check your template dimensions. The 1200x630px ratio (1.91:1) is critical.
Slow generationSlow Generation
If images take too long:
- Pre-generate during build instead of runtime
- Add CDN caching (Cloudflare, Vercel Edge)
- Use a simpler template with fewer elements
Api errorsAPI Errors
Wrap your image generation in error handling with a fallback:
async function getOGImage(title: string): Promise<string> {
try {
const response = await fetch(/* ... */);
const data = await response.json();
return data.url;
} catch (error) {
console.error('OG image generation failed:', error);
return '/images/default-og.png'; // Fallback
}
}Never let a broken OG image break your page.
Measuring impactMeasuring Impact
Track these metrics before and after implementing dynamic OG images:
Social engagement:
- Click-through rate on shared links
- Share counts per post
- Social referral traffic
Brand metrics:
- Visual consistency scores
- Brand mention sentiment
Most sites see measurable improvement within the first month. See 10 ways businesses use image APIs for more examples of the impact.
FaqFAQ
Do i need a different og image for each social platformDo I need a different OG image for each social platform?
No. One 1200x630px image works across all major platforms. Twitter, Facebook, LinkedIn, and Slack all accept this size.
How much does dynamic og generation costHow much does dynamic OG generation cost?
With Imejis.io, you pay per image generated. At $0.015 per image on the Basic plan, generating 1,000 OG images costs $15/month. Caching reduces this significantly.
Can i include emojis in og titlesCan I include emojis in OG titles?
Yes, if your template font supports them. Test specific emojis before deploying—some render differently across platforms.
What happens if the api is slow or downWhat happens if the API is slow or down?
Always have a fallback image. Your site should work without the dynamic image—just with a generic preview instead.
Should i regenerate og images when i update contentShould I regenerate OG images when I update content?
For title or major visual changes, yes. Minor edits usually don't warrant regeneration. Build logic to detect significant changes.
Start generatingStart Generating
The setup takes an afternoon. The benefit lasts as long as your site exists.
Start here:
- Create an OG template in Imejis.io
- Add the API integration to your framework
- Update your meta tags to use dynamic URLs
- Test with social platform debugging tools
- Deploy and share
Every page you publish from now on gets a professional, branded preview image automatically.