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), 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).
- 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).
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:
<!-- /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).
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 |
|---|---|---|
| blog-og | 2 | |
| x | blog-og | 1 |
| 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).
- 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).