Add OG images to every page with Cloudflare Workers — SnapOG

3 min read Original article ↗

If your site is behind Cloudflare, you can use a Worker to add a SnapOG og:image tag to every page — without touching your origin server.

How it works

  1. A visitor (or social crawler) requests a page through Cloudflare.
  2. The Worker fetches the page from your origin.
  3. Cloudflare's HTMLRewriter streams through the HTML, adding or replacing the og:image meta tag to point at snapog.com/s/<your-page-url>.
  4. The modified response is returned to the visitor.

Unlike regex-based rewriting, HTMLRewriter is a streaming HTML parser — it doesn't buffer the entire page in memory, so it's fast even on large pages.

Setup

1. Create a Worker

If you haven't already, install Wrangler and scaffold a new project:

shell

npm create cloudflare@latest snapog-og-image

Replace the generated worker code with one of the scripts below.

Every page gets a SnapOG card, even if the origin already sets one.

Pages that already have an og:image keep theirs. SnapOG only fills in the gaps.

javascript

export default {
  async fetch(request) {
    const response = await fetch(request);
    const contentType = response.headers.get("content-type") || "";

    if (!contentType.includes("text/html")) {
      return response;
    }

    const pageUrl = encodeURIComponent(request.url);
    const ogImage = `<meta property="og:image" content="https://snapog.com/s/${pageUrl}" />`;
    let hasOgImage = false;

    return new HTMLRewriter()
      .on('meta[property="og:image"]', {
        element(el) {
          hasOgImage = true;
          el.replace(ogImage, { html: true });
        }
      })
      .on("head", {
        element(el) {
          el.onEndTag((end) => {
            if (!hasOgImage) {
              end.before(ogImage, { html: true });
            }
          });
        }
      })
      .transform(response);
  }
};

javascript

export default {
  async fetch(request) {
    const response = await fetch(request);
    const contentType = response.headers.get("content-type") || "";

    if (!contentType.includes("text/html")) {
      return response;
    }

    const pageUrl = encodeURIComponent(request.url);
    const ogImage = `<meta property="og:image" content="https://snapog.com/s/${pageUrl}" />`;
    let hasOgImage = false;

    return new HTMLRewriter()
      .on('meta[property="og:image"]', {
        element() { hasOgImage = true; }
      })
      .on("head", {
        element(el) {
          // onEndTag fires after all children have been processed,
          // so hasOgImage is set by then if the tag exists
          el.onEndTag((end) => {
            if (!hasOgImage) {
              end.before(ogImage, { html: true });
            }
          });
        }
      })
      .transform(response);
  }
};

2. Configure the route

In your wrangler.toml, set up a route so the Worker runs on your domain:

toml

name = "snapog-og-image"
main = "src/index.js"
compatibility_date = "2024-01-01"

routes = [
  { pattern = "yoursite.com/*", zone_name = "yoursite.com" }
]

The pattern controls which URLs the Worker handles. Some examples:

  • yoursite.com/* — all pages
  • yoursite.com/blog/* — only blog pages
  • *.yoursite.com/* — all subdomains

You can also configure routes in the Cloudflare dashboard under Workers Routes if you prefer not to use Wrangler.

3. Deploy

What the script does

  • Fetches the page from your origin with fetch(request) — Cloudflare handles this as a normal proxy request.
  • Non-HTML responses pass straight through with no modification.
  • For HTML responses, HTMLRewriter streams through the document looking for <meta property="og:image"> tags and the </head> closing tag.
  • Depending on the mode, it either replaces the existing tag or injects one if none was found.

Verifying it works

After deploying, check any page on your site:

shell

curl -s https://yoursite.com/some-page | grep og:image

You should see something like:

html

<meta property="og:image" content="https://snapog.com/s/https%3A%2F%2Fyoursite.com%2Fsome-page" />

If you still see the old tag, you may need to purge the Cloudflare cache for that URL.

You can also paste the URL into the Facebook Sharing Debugger or Twitter Card Validator to see the card that social platforms will display.

Caching

SnapOG caches rendered images for about a week. If you need to force a refresh after updating a page, see the cache refresh docs.