Multiple Domains & Environments

One account across every domain, subdomain, and environment

For a single site, the connection tag is the right tool: one paste, no keys. Reach for this when one site isn’t the whole picture:

  • Multiple environments: staging and production under one account.
  • Subdomains: a product where each account or page is its own subdomain under one apex.
  • Separate sites: several properties you run, kept on one account, one bill, one dashboard.

Available on the Business plan.

How it works

Instead of a connection tag per host, your app signs the OpenGraph+ image URL for the page being shared and outputs it as the og:image tag. The signature carries your public key and an HMAC of the request, so OpenGraph+ knows the request is yours and renders that exact page. Renders from every domain and subdomain roll up to one site under your account.

Signing happens on each request, so this is for server-rendered apps. A static site generator can’t sign per request; for those, use a connection tag per site.

Rails

Install the opengraphplus gem, set your API key, and include the controller concern. It signs request.url for you, so every domain and subdomain emits the right tag with no per-host setup:

# Gemfile
gem "opengraphplus"

# config/initializers/opengraphplus.rb
OpenGraphPlus.configure do |ogplus|
  ogplus.api_key = ENV["OGPLUS_API_KEY"]
end

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include OpenGraphPlus::Rails::Controller
end

Render the tags in your layout <head>:

<%= open_graph_meta_tags %>

Other frameworks

The signed URL has three parts: your public key, an HMAC-SHA256 of the request path signed with your secret key (truncated to 16 bytes), and the page URL. Both come from your dashboard’s API Keys page. Build the query string once and use it in both the signature input and the final URL, so the encoding always matches.

The URL format:

https://opengraphplus.com/api/websites/v1/{signature}/image?url={page-url}

where signature = base64url(public_key + ":" + hmac_sha256(secret_key, "/image?" + query)[0..15]).

Node.js

import crypto from "node:crypto";

function ogplusImage(pageUrl, { publicKey, secretKey }) {
  const query = new URLSearchParams({ url: pageUrl }).toString();
  const hmac = crypto.createHmac("sha256", secretKey).update(`/image?${query}`).digest();
  const payload = Buffer.concat([Buffer.from(`${publicKey}:`), hmac.subarray(0, 16)]);
  const signature = payload.toString("base64url");
  return `https://opengraphplus.com/api/websites/v1/${signature}/image?${query}`;
}

PHP

function ogplus_image(string $pageUrl, string $publicKey, string $secretKey): string {
    $query = http_build_query(['url' => $pageUrl]);
    $hmac = substr(hash_hmac('sha256', "/image?{$query}", $secretKey, true), 0, 16);
    $signature = rtrim(strtr(base64_encode("{$publicKey}:{$hmac}"), '+/', '-_'), '=');
    return "https://opengraphplus.com/api/websites/v1/{$signature}/image?{$query}";
}

Python

import base64, hashlib, hmac
from urllib.parse import urlencode

def ogplus_image(page_url, public_key, secret_key):
    query = urlencode({"url": page_url})
    digest = hmac.new(secret_key.encode(), f"/image?{query}".encode(), hashlib.sha256).digest()[:16]
    payload = f"{public_key}:".encode() + digest
    signature = base64.urlsafe_b64encode(payload).rstrip(b"=").decode()
    return f"https://opengraphplus.com/api/websites/v1/{signature}/image?{query}"

Output the result as your og:image, and add twitter:card so platforms render the large card:

<meta property="og:image" content="{ ogplus_image(current_page_url) }">
<meta name="twitter:card" content="summary_large_image">

Automatic Open Graph for every page

Set up automatic Open Graph tags in under 10 minutes.