api/pixel.php

<?php
declare(strict_types=1);

require_once __DIR__ . '/../includes/core.php';
require_once __DIR__ . '/../includes/backup.php';

/*
|--------------------------------------------------------------------------
| Tracking pixel endpoint
|--------------------------------------------------------------------------
|
| Collects one pageview, updates daily counters, then returns a transparent
| 1x1 PNG pixel.
|
*/

/*
|--------------------------------------------------------------------------
| Ignore admin visits
|--------------------------------------------------------------------------
*/

if (($_COOKIE['brivacia_ignore'] ?? '') === '1') {
    sendPixel();
}

/*
|--------------------------------------------------------------------------
| Bootstrap
|--------------------------------------------------------------------------
*/

$db = brivaciaDb();
maybeBackupBrivaciaDb();

$day = date('Y-m-d');

/*
|--------------------------------------------------------------------------
| Input
|--------------------------------------------------------------------------
*/

$site = param('site');
$page = param('page');
$trackedWebsiteLang = strtolower(substr(param('lang'), 0, 10));
$ref = param('ref', '__missing__');
$url = substr(param('url'), 0, 500);

if ($ref === '__missing__') {
    $ref = $_SERVER['HTTP_REFERER'] ?? '';
}

// Keep the language even when the tracked site only returns a fallback /pageid URL.
// Priority: explicit pixel lang, then current URL path, then referrer path.
$trackedWebsiteLang = brivaciaInferTrackedWebsiteLang($url, $ref, $trackedWebsiteLang);

if ($site === '' || $page === '') {
    brivaciaLog(
        'pixel/invalid.log',
        'missing required parameter site=' . $site . ' page=' . $page
    );

    sendPixel();
}

$site = strtolower(substr($site, 0, 50));
$page = substr($page, 0, 300);

if (str_starts_with($page, '/') || str_starts_with($page, 'http://') || str_starts_with($page, 'https://')) {
    brivaciaLog(
        'pixel/legacy-page-param.log',
        'site=' . $site .
        ' page=' . $page .
        ' lang=' . $trackedWebsiteLang .
        ' url=' . $url .
        ' ref=' . $ref .
        ' ua=' . ($_SERVER['HTTP_USER_AGENT'] ?? '') .
        ' ip=' . ($_SERVER['REMOTE_ADDR'] ?? '')
    );
}

$pageKey = brivaciaPageKey($site, $page, $trackedWebsiteLang);

if (str_starts_with($pageKey, '/') || preg_match('~^[a-z]{2}/~', $pageKey)) {
    brivaciaLog(
        'pixel/bad-page-key.log',
        'site=' . $site .
        ' page=' . $page .
        ' key=' . $pageKey .
        ' lang=' . $trackedWebsiteLang .
        ' url=' . $url .
        ' ref=' . $ref .
        ' ua=' . ($_SERVER['HTTP_USER_AGENT'] ?? '')
    );
}

if (!isset(brivacia_sites()[$site])) {
    brivaciaLog(
        'pixel/invalid.log',
        'unknown site=' . $site
    );

    sendPixel();
}

/*
|--------------------------------------------------------------------------
| Visitor context
|--------------------------------------------------------------------------
*/

$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
$country = countryFromIp($_SERVER['REMOTE_ADDR'] ?? '');

$kind = detectVisitorKind($ua);
$visitorHash = visitorHash($day, $ua, $_SERVER['REMOTE_ADDR'] ?? '');

/*
|--------------------------------------------------------------------------
| Page title
|--------------------------------------------------------------------------
*/

$title = param('title');

if ($title === '') {
    $title = $site . ' — ' . $page;
}

/*
|--------------------------------------------------------------------------
| Store hit
|--------------------------------------------------------------------------
*/

try {
    $db->beginTransaction();

    ensureDay($db, $day, $site);

    if ($kind === 'human') {
        $isNew = markSeen($db, $day, $visitorHash, $site);
        $isNewSession = markSession($db, $day, $visitorHash, $site);

        if ($isNew) {
            inc($db, 'unique_visitors', $day, $site);
        }

        if ($isNewSession) {
            incCountry($db, $day, $country, $site);

            $referrer = refSourceFast($ref);

            // Discover new referrers immediately
            if ($referrer !== BRIVACIA_UNKNOWN && $referrer !== BRIVACIA_BLOCKED && !isOwnHost($referrer)) {
                discoverReferrer($referrer);
            }

            incReferrer($db, $day, $referrer, $site);
            inc($db, 'visits', $day, $site);
        }

        inc($db, 'pageviews', $day, $site);

        incPage(
            $db,
            $day,
            $site,
            $pageKey,
            $title,
            $url
        );
    } else {
        inc($db, 'bots', $day, $site);
    }

    $db->commit();

} catch (Throwable $e) {
    if ($db->inTransaction()) {
        $db->rollBack();
    }

    brivaciaLog(
        'pixel/failed.log',
        'site=' . $site .
        ' page=' . $page .
        ' kind=' . $kind .
        ' error=' . $e->getMessage()
    );
}

if ($kind === 'human') {
    $pageLimit = brivaciaMaintenancePageLimit($db);

    if ($pageLimit > 0) {
        refreshPageLabels($db, $pageLimit);
    }

    maybeNormalizeStoredReferrers($db);
}

sendPixel();