OG Image on Google Cloud Storage: Host Social Preview Images with GCS
How to host og:image files on Google Cloud Storage — covering public access setup, HTTPS URLs, CORS configuration, and serving via Cloud CDN for fast social previews.
Updated March 2026
Why GCS for OG Images?
Google Cloud Storage (GCS) is a solid choice for hosting static OG images: global CDN distribution, simple public access configuration, and HTTPS by default for all storage.googleapis.com URLs. GCS URLs are always HTTPS — unlike AWS S3 direct URLs — which means no CloudFront equivalent is strictly required.
Step 1: Create a Public Bucket
# Create a bucket (choose your region) gsutil mb -l us-central1 gs://your-bucket-name # Make the bucket publicly readable gsutil iam ch allUsers:objectViewer gs://your-bucket-name # Or via gcloud CLI (recommended for new projects): gcloud storage buckets create gs://your-bucket-name --location=us-central1 --uniform-bucket-level-access gcloud storage buckets add-iam-policy-binding gs://your-bucket-name --member=allUsers --role=roles/storage.objectViewer
Note: GCS now encourages Uniform bucket-level access (as above) over per-object ACLs. With uniform access + allUsers objectViewer, all objects in the bucket are publicly readable.
Step 2: Upload Your OG Images
# Upload a single OG image with correct Content-Type gsutil -h "Content-Type:image/png" -h "Cache-Control:public, max-age=31536000" cp og-image.png gs://your-bucket-name/og/page-slug.png # Upload multiple images gsutil -m -h "Content-Type:image/png" -h "Cache-Control:public, max-age=31536000" cp og/*.png gs://your-bucket-name/og/ # Using gcloud CLI gcloud storage cp og-image.png gs://your-bucket-name/og/page-slug.png --cache-control="public, max-age=31536000"
Step 3: Use the Public URL in Your og:image Tag
GCS public URLs follow this format — and they're always HTTPS:
<!-- Direct GCS URL (HTTPS by default) --> <meta property="og:image" content="https://storage.googleapis.com/your-bucket-name/og/page-slug.png" /> <meta property="og:image:width" content="1200" /> <meta property="og:image:height" content="630" /> <meta property="og:image:type" content="image/png" />
CORS Configuration (If Needed)
Most social crawlers don't need CORS. But if you're loading OG images from JavaScript (e.g., canvas-based tools), configure CORS on the bucket:
# cors-config.json
[
{
"origin": ["*"],
"method": ["GET", "HEAD"],
"responseHeader": ["Content-Type"],
"maxAgeSeconds": 3600
}
]
# Apply CORS config
gsutil cors set cors-config.json gs://your-bucket-nameCustom Domain with Cloud CDN
For a branded URL like cdn.yoursite.com/og/..., use a Cloud CDN backend pointing to your GCS bucket:
# 1. Create a backend bucket gcloud compute backend-buckets create og-images-backend --gcs-bucket-name=your-bucket-name --enable-cdn # 2. Create a URL map gcloud compute url-maps create og-images-lb --default-backend-bucket=og-images-backend # 3. Create HTTPS proxy (requires SSL cert) gcloud compute target-https-proxies create og-https-proxy --url-map=og-images-lb --ssl-certificates=your-ssl-cert # 4. Create forwarding rule gcloud compute forwarding-rules create og-https-rule --target-https-proxy=og-https-proxy --ports=443 --global
Point your DNS cdn.yoursite.com to the forwarding rule IP, then use:
<meta property="og:image" content="https://cdn.yoursite.com/og/page-slug.png" />
Uploading from Node.js
import { Storage } from "@google-cloud/storage";
const storage = new Storage({
projectId: process.env.GCP_PROJECT_ID,
credentials: JSON.parse(process.env.GCP_SERVICE_ACCOUNT_KEY!),
});
const bucket = storage.bucket("your-bucket-name");
export async function uploadOgImage(
slug: string,
pngBuffer: Buffer
): Promise<string> {
const file = bucket.file(`og/${slug}.png`);
await file.save(pngBuffer, {
contentType: "image/png",
metadata: {
cacheControl: "public, max-age=31536000, immutable",
},
});
// GCS direct URL (always HTTPS)
return `https://storage.googleapis.com/your-bucket-name/og/${slug}.png`;
}Verify your GCS-hosted OG image →
Paste your URL into OGFixer to confirm the image loads and renders correctly across Twitter, LinkedIn, Discord, and Slack.
Preview my OG image →