Social Preview Caching
What This Means
Social platforms cache your Open Graph and Twitter Card metadata to improve performance. When you update your content, old previews may persist for hours or days. This causes:
- Old images showing after you've updated them
- Previous titles/descriptions appearing in shares
- Broken images after URL changes
- Inconsistent previews across shares
Cache Duration by Platform
| Platform | Cache Duration | Manual Refresh |
|---|---|---|
| Up to 30 days | Sharing Debugger | |
| Twitter/X | ~7 days | Card Validator |
| Up to 7 days | Post Inspector | |
| Slack | Until webhook | Re-post link |
| Discord | ~24 hours | Varies by server |
| ~7 days | No manual refresh |
How to Diagnose
1. Check What's Cached
Facebook:
- Go to Sharing Debugger
- Enter URL and click "Debug"
- Compare "Link Preview" with your current OG tags
- Note "Time Scraped" to see cache age
Twitter:
- Visit Card Validator
- Enter URL
- Compare preview with actual meta tags
LinkedIn:
- Go to Post Inspector
- Enter URL
- Review cached metadata
2. Compare Live vs Cached
// Check what platforms will scrape
fetch('https://example.com/page')
.then(res => res.text())
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
console.log('Current OG Title:',
doc.querySelector('meta[property="og:title"]')?.content);
});
General Fixes
Force Cache Refresh by Platform
Facebook:
# Using Graph API (programmatic)
curl -X POST \
"https://graph.facebook.com/?id=https://example.com/page&scrape=true&access_token=YOUR_TOKEN"
Or manually:
- Go to Sharing Debugger
- Enter your URL
- Click "Scrape Again"
- Repeat if necessary (sometimes needs 2-3 scrapes)
Twitter:
- Open Card Validator
- Enter URL
- Click "Preview Card"
- Cache typically updates within hours
LinkedIn:
- Go to Post Inspector
- Enter URL
- Click "Inspect"
- The scrape refreshes the cache
Slack:
- Unfurl cache clears when URL pattern changes
- Add query parameter to force refresh:
?v=2 - Or wait for automatic expiry (~30 minutes for unfurls)
Cache Busting Techniques
1. Query Parameter Versioning:
<!-- Add version parameter when content changes -->
<meta property="og:image" content="https://example.com/image.jpg?v=20250115">
2. Unique Filenames:
<!-- Use content-hashed filenames -->
<meta property="og:image" content="https://example.com/og-image-abc123.jpg">
3. CDN Cache Invalidation:
# Cloudflare
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
-H "Authorization: Bearer {api_token}" \
-d '{"files":["https://example.com/og-image.jpg"]}'
# AWS CloudFront
aws cloudfront create-invalidation --distribution-id XXXXXX --paths "/og-image.jpg"
Automated Cache Refresh
On Content Update (WordPress):
// Refresh Facebook cache when post is updated
add_action('save_post', 'refresh_facebook_cache', 10, 3);
function refresh_facebook_cache($post_id, $post, $update) {
if (!$update) return;
$url = get_permalink($post_id);
$access_token = get_option('facebook_access_token');
wp_remote_post("https://graph.facebook.com/?id=" . urlencode($url) .
"&scrape=true&access_token=" . $access_token);
}
Using Webhooks:
// Trigger cache refresh on deploy
async function refreshSocialCaches(pageUrl) {
// Facebook
await fetch(`https://graph.facebook.com/?id=${encodeURIComponent(pageUrl)}&scrape=true`);
// LinkedIn (requires authentication)
// Note: LinkedIn doesn't have a public API for this
console.log(`Cache refresh triggered for: ${pageUrl}`);
}
Prevent Caching Issues
1. Use absolute, stable URLs:
<!-- Good: Absolute, versioned URL -->
<meta property="og:image" content="https://cdn.example.com/v2/og-image.jpg">
<!-- Bad: Relative or dynamic URL -->
<meta property="og:image" content="/images/og-image.jpg">
2. Set appropriate cache headers:
# Nginx: Allow crawlers to get fresh content
location /og-images/ {
add_header Cache-Control "public, max-age=86400";
add_header Vary "User-Agent";
}
3. Implement og:updated_time:
<meta property="og:updated_time" content="2025-01-15T10:30:00Z">
Platform-Specific Guides
| Platform | Guide |
|---|---|
| Shopify | Shopify Cache Refresh |
| WordPress | WordPress Social Cache |
Verification
- Use platform debuggers to verify fresh content
- Share in private group to test preview
- Check from incognito/different account
- Monitor cache refresh success in logs
Common Mistakes
| Mistake | Fix |
|---|---|
| Not waiting for scrape to complete | Click "Scrape Again" multiple times |
| Old image URL still resolving | Update filename, not just file |
| CDN serving stale content | Purge CDN cache before social refresh |
| Using JavaScript-only OG tags | Ensure SSR for social crawlers |