# A/B testing Open Graph images: what platforms allow, and a test that holds up

> How to A/B test Open Graph images when every platform caches one preview per URL: separate variant URLs, og:url, UTM tags, and the maths of the result.

Published 2026-11-08 · https://shareglint.com/en/guides/og-image-ab-test

Everyone who makes social images wonders which one gets more clicks: the photo or the headline card, the dark or the light one, with or without a face. An A/B test can answer that, but the usual web A/B setup — one URL, a random variant per visitor — does not work for link previews. This page explains why, gives a test design that does work, and is plain about what can be measured.

**Sources and checks.** Platform behaviour is quoted from Meta's developer documentation and X's archived card docs as read on 2026-11-08. The counting behaviour of our dashboard was checked on our development stack the same day by fetching two variants as Facebook's, X's and LinkedIn's crawlers.

## Why the usual A/B test does not work here

A preview is built once per URL by the platform's crawler and then cached:

- **Facebook** refreshes a URL's link data "automatically every 30 days" ([Meta: change a link](https://developers.facebook.com/documentation/sharing/webmasters/getting-started/change-link.md)), unless someone scrapes it again in the Sharing Debugger.
- **X** re-reads a page's card tags "roughly every seven days" ([X's archived card docs](https://web.archive.org/web/2024/https://developer.x.com/en/docs/twitter-for-websites/cards/guides/troubleshooting-cards)).
- **Facebook groups URLs by `og:url`**: "All links that specify the same canonical URL are treated as the same resource by Facebook's link sharing infrastructure for the purpose of metrics and metadata (link image, title, etc.)" ([Meta: canonical URL](https://developers.facebook.com/documentation/sharing/webmasters/getting-started/versioned-link.md)).

So serving a random image per request gives everyone whichever image the crawler happened to get, and two URLs with the same `og:url` collapse into one on Facebook. The variant has to live in the URL that is shared.

## A test design that holds up

**1. One page URL per variant.** The same content, reachable as `/post?v=a` and `/post?v=b`. On each, the tags name that variant:

```html
<!-- /post?v=b -->
<meta property="og:url" content="https://example.com/post?v=b">
<meta property="og:image" content="https://example.com/og/post-b.png">
<meta name="twitter:card" content="summary_large_image">
<link rel="canonical" href="https://example.com/post">
```

`og:url` points at the variant so Facebook keeps them apart; `rel="canonical"` stays the clean URL, so search engines still see one page. The cost: Facebook's share counts are split between the variants for the duration of the test.

**2. Different image URLs.** Give each variant's image its own address (`post-a.png`, `post-b.png`). Never replace the file behind one image URL during a test: caches on the platform's side and in CDNs keep the old file.

**3. Tag the clicks.** The `v` parameter already marks which variant a visit came from, and it is part of `og:url`, so it survives even if a platform sends the click to the canonical address it stored. Count visits per `v` in your analytics. Where you control the link (a newsletter, your own posts), add UTM tags too: `/post?v=b&utm_source=linkedin&utm_medium=social&utm_content=og-b`. The platform's own post analytics reports impressions per post.

**4. Share them to comparable audiences.** Organic posts have no built-in split: the same audience sees both if you post both. Options that keep the comparison fair:

- **Alternate** the variants across a series of similar posts (A on odd weeks, B on even), so time and topic average out.
- **Split a list** you control — a newsletter or a community — at random into two halves, one link each.
- **Use the ad platform's own split test** for paid posts, where the platform assigns the audience; the creative is just the image you upload.

**5. Decide the sample size first.** Click-through rates on social are low, so differences are small and noise is large. A two-proportion test on example numbers:

| Variant A | Variant B | Rates | Two-sided p |
|---|---|---|---|
| 40 clicks / 2,000 impressions | 48 / 2,000 | 2.0% vs 2.4% | 0.39 |
| 40 / 2,000 | 56 / 2,000 | 2.0% vs 2.8% | 0.10 |
| 400 / 20,000 | 560 / 20,000 | 2.0% vs 2.8% | < 0.001 |

The same 40% relative difference is noise at 2,000 impressions per variant and clear at 20,000. Pick the number before you start and do not stop on the first good day — checking every morning and stopping when it looks good finds "winners" that are not.

## Making the variants

The two images should differ in one thing you want to learn about — layout, colour, headline wording, a photo or none — so the result means something. With templates, one variant is one template or one set of fields: render both for the same post with the same title and send each URL its own image. A signed image URL per variant works without a build step; the image renders on the crawler's first visit and is cached afterwards ([signed image URLs](https://shareglint.com/en/guides/signed-image-urls)).

## What our dashboard does and does not count

Each time an image is served through a signed URL (`/i/`, `/u/` or `/s/`), the dashboard adds one to a daily counter per platform and per template. We checked it by fetching variant A (template `blog-og`) twice as Facebook's crawler and once as X's, and variant B (`quote-og`) once as LinkedIn's crawler and once from a browser. That day's counters read:

| Platform | Template | Fetches |
|---|---|---|
| facebook | blog-og | 2 |
| x | blog-og | 1 |
| linkedin | quote-og | 1 |
| browser | quote-og | 1 |

That tells you each platform did pick up each variant — useful for spotting a variant whose image never loaded. It is not an impression count: one crawler fetch serves a preview to everyone who sees the post, and crawlers return on their own schedule (our redirect is cacheable for 1 h, then they come back through us). It is also not clicks. Clicks are visits to your page, and they come from your analytics with the UTM tags above. Variants made from the same template with different fields count together, so for a per-variant view use one template per variant.

## Things that spoil a test

- **Testing with a cached URL.** A URL that was shared before the test already has a preview; start with fresh variant URLs.
- **Different posting times or captions.** The caption and the hour usually matter more than the image; keep them identical.
- **Unequal image loading.** A variant whose image renders slowly can be cached imageless by the first crawler. Warm both image URLs before sharing, and check each in the platform's preview tool ([og:image not showing](https://shareglint.com/en/guides/og-image-not-showing)).
- **Believing a headline number from elsewhere.** Published "+X% clicks from OG images" figures come from someone else's audience and setup; your own test is the only one that answers your question.

Rendering both variants costs one render each (more for animated images), and repeated identical images are served from cache without a new render ([pricing](https://shareglint.com/en/pricing)).

## FAQ

### Can I A/B test my og:image?

Not by swapping images under one URL: platforms cache one preview per URL (Facebook refreshes link data about every 30 days, X roughly every seven) and show it to everyone. Give each variant its own page URL, with its own og:url and og:image, tag each with a UTM parameter, share them to comparable audiences, and compare clicks in your analytics.

### Why do my two variant URLs show the same image on Facebook?

Because they share an og:url. Meta's docs: "All links that specify the same canonical URL are treated as the same resource by Facebook's link sharing infrastructure for the purpose of metrics and metadata (link image, title, etc.)." Each variant page needs og:url pointing at itself.

### How many clicks do I need before trusting the result?

More than most people expect. 40 against 56 clicks from 2,000 impressions each (2.0% vs 2.8%) is not significant (p ≈ 0.10 in a two-proportion test); the same rates over 20,000 impressions each are (p < 0.001). Decide the sample size before you start and do not stop at the first good-looking day.

### Does the image service tell me which variant got more clicks?

No. Our dashboard counts how often each platform's crawler fetched each template's image, per day — proof that a variant was picked up, not impressions or clicks. Clicks come from the UTM-tagged visits in your own analytics.
