PHP Open Graph Meta Tags: Add OG Tags to Any PHP Site
How to add og:title, og:image, og:description, and Twitter card meta tags to plain PHP pages, WordPress themes, and PHP frameworks — with copy-paste examples.
Basic PHP OG tags (any page)
OG tags are plain HTML <meta> tags in the <head>. In PHP you output them like any other HTML — with dynamic values from your database or variables:
<?php // Fetch your page data $title = htmlspecialchars($page['title']); $description = htmlspecialchars($page['excerpt']); $image = 'https://yourdomain.com/images/og/' . $page['slug'] . '.png'; $url = 'https://yourdomain.com/' . $page['slug']; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title><?= $title ?></title> <meta name="description" content="<?= $description ?>" /> <!-- Open Graph --> <meta property="og:title" content="<?= $title ?>" /> <meta property="og:description" content="<?= $description ?>" /> <meta property="og:image" content="<?= $image ?>" /> <meta property="og:url" content="<?= $url ?>" /> <meta property="og:type" content="article" /> <meta property="og:site_name" content="My Site" /> <!-- Twitter / X --> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content="<?= $title ?>" /> <meta name="twitter:description" content="<?= $description ?>" /> <meta name="twitter:image" content="<?= $image ?>" /> <link rel="canonical" href="<?= $url ?>" /> </head> <body> <!-- page content --> </body> </html>
Always run values through htmlspecialchars() to prevent broken attributes from unescaped quotes or angle brackets.
Shared header partial (DRY approach)
Most PHP sites use an included header partial. Pass OG data as variables before including it:
<?php // post.php require_once 'db.php'; $post = get_post($_GET['slug']); $og = [ 'title' => $post['title'], 'description' => substr(strip_tags($post['body']), 0, 160), 'image' => 'https://yourdomain.com/og/' . $post['slug'] . '.jpg', 'url' => 'https://yourdomain.com/post/' . $post['slug'], 'type' => 'article', ]; include 'partials/header.php'; ?> <!-- page body --> <?php include 'partials/footer.php'; ?>
<?php // partials/header.php $og = $og ?? [ 'title' => 'My Site — Default Title', 'description' => 'Default meta description for social sharing.', 'image' => 'https://yourdomain.com/images/default-og.png', 'url' => 'https://yourdomain.com' . $_SERVER['REQUEST_URI'], 'type' => 'website', ]; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title><?= htmlspecialchars($og['title']) ?></title> <meta property="og:title" content="<?= htmlspecialchars($og['title']) ?>" /> <meta property="og:description" content="<?= htmlspecialchars($og['description']) ?>" /> <meta property="og:image" content="<?= htmlspecialchars($og['image']) ?>" /> <meta property="og:url" content="<?= htmlspecialchars($og['url']) ?>" /> <meta property="og:type" content="<?= htmlspecialchars($og['type']) ?>" /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:image" content="<?= htmlspecialchars($og['image']) ?>" /> <link rel="canonical" href="<?= htmlspecialchars($og['url']) ?>" /> </head> <body>
Dynamic OG images with PHP + GD
PHP's GD library can generate OG images on the fly — useful when you don't have pre-generated assets:
<?php // og-image.php — returns a PNG
header('Content-Type: image/png');
header('Cache-Control: public, max-age=86400');
$title = htmlspecialchars_decode($_GET['title'] ?? 'My Page');
$width = 1200;
$height = 630;
$img = imagecreatetruecolor($width, $height);
$bg = imagecolorallocate($img, 10, 10, 10);
$text = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $bg);
// Use a larger built-in font (5 is the largest GD built-in)
imagestring($img, 5, 60, 200, $title, $text);
imagepng($img);
imagedestroy($img);Reference it as your OG image URL:
<meta property="og:image" content="https://yourdomain.com/og-image.php?title=<?= urlencode($post['title']) ?>" />
For production use, consider caching the generated PNG to disk so it doesn't regenerate on every scraper request.
Common PHP OG mistakes
- Unescaped quotes in attributes — always use
htmlspecialchars()on every dynamic value. - Wrong image dimensions — use 1200×630px (1.91:1) for all platforms. Smaller images fall back to inline thumbnails.
- Relative image URLs —
og:imagemust be an absolute HTTPS URL. Scrapers don't resolve relative paths. - Output buffering issues — headers must be sent before any output. If you get "headers already sent" errors, move OG tag output before any echo/print.
Verify your PHP OG tags
After deploying, paste your URL into OGFixer to instantly see how your PHP page previews on Twitter, LinkedIn, Slack, and Discord — and catch missing or broken tags before sharing.