feat: add Open Graph and X Card meta tags with server-side crawler proxy
This commit is contained in:
112
docs/pow-server/og-proxy.php
Normal file
112
docs/pow-server/og-proxy.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/**
|
||||
* OG Meta Tag Proxy for Social Media Crawlers
|
||||
*
|
||||
* Setup: Nginx/Apache rewrite rule on dgray.io:
|
||||
* If User-Agent matches crawler → proxy to this script
|
||||
* Else → serve static index.html
|
||||
*
|
||||
* Example Nginx config:
|
||||
* if ($http_user_agent ~* "Twitterbot|facebookexternalhit|TelegramBot|Discordbot|Slackbot|LinkedInBot|WhatsApp") {
|
||||
* proxy_pass https://pow.dgray.io/og-proxy.php;
|
||||
* }
|
||||
*/
|
||||
|
||||
require __DIR__ . '/config.php';
|
||||
|
||||
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
|
||||
|
||||
// Extract listing ID from hash URL or query param
|
||||
// Crawlers may receive: /listing/UUID or ?listing=UUID
|
||||
$listingId = null;
|
||||
|
||||
if (preg_match('#/listing/([a-f0-9-]{36})#i', $requestUri, $matches)) {
|
||||
$listingId = $matches[1];
|
||||
}
|
||||
|
||||
if (!$listingId && isset($_GET['listing'])) {
|
||||
$listingId = $_GET['listing'];
|
||||
}
|
||||
|
||||
$siteUrl = 'https://dgray.io';
|
||||
$defaultTitle = 'dgray.io – Anonymous Classifieds with Monero';
|
||||
$defaultDesc = 'Buy and sell anonymously with Monero. No KYC, no email, E2E encrypted chat.';
|
||||
$defaultImage = $siteUrl . '/assets/press/og-image.png';
|
||||
|
||||
$title = $defaultTitle;
|
||||
$description = $defaultDesc;
|
||||
$image = $defaultImage;
|
||||
$url = $siteUrl;
|
||||
$type = 'website';
|
||||
|
||||
if ($listingId) {
|
||||
$apiUrl = DIRECTUS_URL . '/items/listings/' . urlencode($listingId)
|
||||
. '?fields=id,title,description,price,currency,images.directus_files_id.id';
|
||||
|
||||
$ch = curl_init($apiUrl);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Authorization: Bearer ' . DIRECTUS_TOKEN,
|
||||
],
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 5,
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$data = json_decode($response, true);
|
||||
$listing = $data['data'] ?? null;
|
||||
|
||||
if ($listing) {
|
||||
$title = htmlspecialchars($listing['title'] ?? '') . ' – dgray.io';
|
||||
$description = htmlspecialchars(mb_substr($listing['description'] ?? '', 0, 160));
|
||||
$url = $siteUrl . '/#/listing/' . $listing['id'];
|
||||
$type = 'product';
|
||||
|
||||
$imageId = $listing['images'][0]['directus_files_id']['id']
|
||||
?? $listing['images'][0]['directus_files_id']
|
||||
?? null;
|
||||
|
||||
if ($imageId) {
|
||||
$image = DIRECTUS_URL . '/assets/' . $imageId . '?width=1200&height=630&fit=cover';
|
||||
}
|
||||
|
||||
if (!empty($listing['price']) && !empty($listing['currency'])) {
|
||||
$price = number_format((float)$listing['price'], 2);
|
||||
$description .= " | {$price} {$listing['currency']}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= $title ?></title>
|
||||
<meta name="description" content="<?= $description ?>">
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="<?= $type ?>">
|
||||
<meta property="og:site_name" content="dgray.io">
|
||||
<meta property="og:title" content="<?= $title ?>">
|
||||
<meta property="og:description" content="<?= $description ?>">
|
||||
<meta property="og:url" content="<?= $url ?>">
|
||||
<meta property="og:image" content="<?= $image ?>">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
|
||||
<!-- X (Twitter) Card -->
|
||||
<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 ?>">
|
||||
|
||||
<!-- Redirect real users to the actual page -->
|
||||
<meta http-equiv="refresh" content="0;url=<?= $url ?>">
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to <a href="<?= $url ?>"><?= $title ?></a></p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user