ADS-004
Verify that someone owns the site they registered
Fetch the page, look for your token in a meta tag, and only let verified sites earn. The empty-needle bug in this check is worth knowing about before it bites you.
Anyone can type any domain into a form. If unverified sites can earn or receive traffic, someone will register a site they do not own — or twenty sites that do not exist — and farm the difference.
Verification is simple: issue a token, ask the owner to put it in a meta tag in the page head, then fetch the page from your server and look for it. What makes it worth writing down is a failure mode specific to PHP. If the stored token is empty or NULL, stripos with an empty needle returns 0, which is a valid position, which passes a loose check. Every site with a missing token verifies instantly and silently.
Guarantee the token is non-empty before you compare, and re-check periodically — a site that removes the tag after verifying should lose its status.
function verify_site(PDO $pdo, int $siteId): bool
{
$st = $pdo->prepare('SELECT url, verify_token FROM sites WHERE id = ?');
$st->execute([$siteId]);
$site = $st->fetch(PDO::FETCH_ASSOC);
// An empty token makes stripos() return 0 for ANY haystack. Guard it first.
$token = trim((string) ($site['verify_token'] ?? ''));
if ($site === false || $token === '') {
return false;
}
$html = fetch_guarded($site['url']); // SSRF-guarded fetch
if ($html === null) {
return false;
}
// Match the tag, not just the token loose in the page body.
$pattern = '~<meta\s+name=["\']site-verification["\']\s+content=["\']'
. preg_quote($token, '~') . '["\']~i';
$ok = (bool) preg_match($pattern, $html);
$pdo->prepare('UPDATE sites SET verified = ?, verified_checked_at = NOW() WHERE id = ?')
->execute([$ok ? 1 : 0, $siteId]);
return $ok;
}
Using it
Bind every earning object — ad slot, link, widget — to a verified site, and check the request's referring host against that site when you count a paid event.
Re-verify on a schedule. A cron that walks sites whose last check is older than a day, and un-verifies the ones that dropped the tag, closes the verify-then-remove loop.
What bites people
Matching the bare token anywhere in the page means anyone who can post a comment on the target site can verify it. Match the whole tag.
Gate earning on verification, never content. If an unverified request still has to be served, serve it and pay nothing — breaking the page instead will cost you the publisher.
Fetch with an SSRF guard. The URL came from a user.