Phoenix
PhoenixPhoenix
Generate a unique OG image for every page, or any on-demand graphic, from a single Imejis template. The pattern below uses a Phoenix controller action as a thin proxy: your API key stays on the server, and the browser (and social crawlers) only ever see your own URL.
Set two environment variables first: IMEJIS_API_KEY (from your dashboard) and IMEJIS_DESIGN_ID (any design's ID).
IMEJIS_API_KEY=your_api_key
IMEJIS_DESIGN_ID=your_design_id1 a controller that renders the image1. A controller that renders the image
This action takes a title query param, POSTs it to Imejis as a component.property override with the dma-api-key header, and returns the finished image bytes. Because the key is sent server-side, it never reaches the client.
defmodule MyAppWeb.OgController do
use MyAppWeb, :controller
def show(conn, params) do
title = Map.get(params, "title", "Untitled")
design_id = System.get_env("IMEJIS_DESIGN_ID")
api_key = System.get_env("IMEJIS_API_KEY")
%Req.Response{body: image} =
Req.post!("https://render.imejis.io/v1/#{design_id}",
headers: [{"dma-api-key", api_key}],
json: %{"headline.text" => title}
)
conn
|> put_resp_content_type("image/jpeg")
# Renders are deterministic, so cache aggressively at the edge/CDN.
|> put_resp_header(
"cache-control",
"public, immutable, no-transform, max-age=31536000"
)
|> send_resp(200, image)
end
endWire the action into your router:
scope "/", MyAppWeb do
pipe_through :browser
get "/og", OgController, :show
end2 point your template at it2. Point your template at it
Reference the route from your HEEx template or meta tags, passing each page's real data. Social platforms fetch /og?title=… from your own domain, no key exposed.
<% og_image = "https://your-site.com/og?title=" <>
URI.encode_www_form(@post.title) %>
<meta property="og:image" content="{og_image}" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="{og_image}" />Override any field. Each dynamic component exposes keys like headline.text, title.color, or image.image. Send only the ones you want to change. A design's overridable fields are listed in its Share / API panel.