WordPress

OG images in
WordPress

Generate on publish, store the URL in post meta.

Where it plugs in

In WordPress you do not want to hit the API on every page view. Hook into the post save, generate once, and store the URL in a meta field that your theme or SEO plugin reads later.

functions.php

add_action('save_post_post', function (int $post_id, WP_Post $post): void {
    if (wp_is_post_revision($post_id) || $post->post_status !== 'publish') {
        return;
    }

    $response = wp_remote_post('https://imageapi.dev/v1/images?wait=true', [
        'timeout' => 15,
        'headers' => [
            'Authorization' => 'Bearer ' . IMAGE_API_KEY,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode([
            'template' => 'blog-og',
            'modifications' => [
                'title'  => get_the_title($post),
                'author' => get_the_author_meta('display_name', $post->post_author),
                'site'   => wp_parse_url(home_url(), PHP_URL_HOST),
            ],
        ]),
    ]);

    if (is_wp_error($response)) {
        return;
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    if (! empty($body['url'])) {
        update_post_meta($post_id, '_og_image', esc_url_raw($body['url']));
    }
}, 10, 2);

// Print it in <head> if you are not using an SEO plugin.
add_action('wp_head', function (): void {
    if (! is_singular('post')) {
        return;
    }

    $image = get_post_meta(get_the_ID(), '_og_image', true);

    if ($image) {
        printf('<meta property="og:image" content="%s">' . "\n", esc_attr($image));
        echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
    }
});
The trap

The `save_post` hook also fires on autosaves and on every update. The `post_status` and `wp_is_post_revision` guards are what stop you from generating a dozen images while writing a single post.

What comes back

With ?wait=true the finished image arrives on the same connection — usually in about a second.

{
    "id": "img_01m08s3ez1zcv28h335g9923bw",
    "status": "completed",
    "url": "https://cdn.imageapi.dev/renders/img_01m08s3ez1zcv28h335g9923bw.png",
    "duration_ms": 912
}

What it costs

A hundred images a month free, then $9 for two thousand. The same post rendered twice returns the existing URL and uses no quota — so rebuilding your site costs nothing.

Other frameworks