=== Pagemetrics for Matomo ===
Contributors: pagemachine, maltamirano
Tags: matomo, analytics, tracking, server-side, privacy, ai
Requires at least: 6.1
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 1.1.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Pagemetrics for Matomo adds server-side, privacy-friendly analytics to WordPress. It tracks page views, downloads, and AI assistant bot crawls without using JavaScript.

== Description ==

Pagemetrics for Matomo adds privacy-friendly, server-side analytics to WordPress by
leveraging the `pagemachine/matomo-tracking` PHP library. When enabled, the
plugin sends page view and optional download events from your WordPress site
directly to a Matomo instance without loading Matomo's JavaScript tracker.

Key benefits:

* Track page views on the server with full control over attributes such as title, URL and referrer.
* Optional download tracking rewrites file links and records the click before redirecting visitors.
* Optional AI assistant bot tracking detects crawls from ChatGPT, Claude, Perplexity and others and forwards them to Matomo's dedicated AI Assistants report.
* Multisite aware – network admins can define defaults, individual sites can override them.
* Respects Do Not Track and Global Privacy Control headers through the underlying library.
* Logs issues to the WordPress debug log when `WP_DEBUG` is enabled.

Looking for expert help with Matomo or server-side tracking? **Pagemachine** offers
consulting, implementation and ongoing support via our **Pagemetrics** solution.
More info: [Pagemetrics.eu](https://pagemetrics.eu/)

== Installation ==

1. Upload the `pagemetrics-for-matomo` plugin directory (including the bundled `vendor/`
   folder) to your site's `wp-content/plugins` path.
2. Activate the plugin through the **Plugins → Pagemetrics for Matomo** screen in WordPress.
3. Open **Settings → Pagemetrics for Matomo** and configure:
   * Matomo URL (e.g. `https://matomo.example.com/`)
   * Default Matomo site ID
   * Optional auth token (required for IP tracking and other privileged attributes)
   * HTTP timeout for Matomo requests
   * Download tracking toggle, if you want the plugin to rewrite file links automatically
   * AI assistant bot tracking toggle, to send AI crawler hits to Matomo's AI Assistants report (requires Matomo 5.8.0 or later)
4. (Multisite) Network administrators can define defaults under **Network Admin → Settings → Pagemetrics for Matomo**. Individual sites can override those values on their local settings page.

The plugin starts sending data as soon as the Matomo URL and site ID are set.

== Frequently Asked Questions ==

= Do I need to share my Matomo auth token? =

No. The auth token is optional. Provide it only if you need to forward visitor
IP addresses or rely on Matomo parameters that require authentication. The
token is stored server-side and never exposed to browsers.

= How is the visitor IP forwarded behind a proxy or CDN? =

When an auth token is set, the plugin forwards the visitor IP to Matomo as the
`cip` parameter, resolved from `REMOTE_ADDR` by default. If your site is behind
a reverse proxy or CDN, use the `pm_matomo_tracking_visitor_ip` filter to return
the real client IP from your trusted forwarded header.

= Can I disable download link rewriting? =

Yes. Leave the _Track downloads_ toggle unchecked in the settings page. You can
also use the `pm_matomo_tracking_should_rewrite_downloads` filter to disable
rewriting programmatically for specific posts or file types.

= How does AI assistant bot tracking work? =

When the _Track AI assistant bots_ toggle is enabled, the plugin inspects the
User-Agent header of every front-end request. If it matches a known AI crawler
(ChatGPT, Claude, Perplexity, MistralAI, Gemini, GoogleAgent, NovaAct), a
server-side telemetry hit is sent to Matomo using `recMode=1`. The hit is
recorded in Matomo's dedicated AI Assistants report and does not count as a
normal visit. Requires Matomo 5.8.0 or later.

= Can I add custom AI bot User-Agents? =

Yes. Use the `pm_matomo_tracking_ai_bot_user_agents` filter to extend or replace
the default list of User-Agent substrings:

    add_filter('pm_matomo_tracking_ai_bot_user_agents', static function (array $substrings): array {
        $substrings[] = 'MyCustomBot';
        return $substrings;
    });

= What happens if Matomo is down? =

Requests use a configurable HTTP timeout (default three seconds). When Matomo
is unreachable, tracking is skipped and a warning is logged (only when
`WP_DEBUG` is enabled). Page rendering continues normally.

== Screenshots ==

1. Pagemetrics for Matomo settings

== Developer Hooks ==

Page view tracking:

* `pm_matomo_tracking_should_track_request` — Return `false` to skip page view tracking for the current request.
* `pm_matomo_tracking_visitor_ip` — Override the visitor IP forwarded to Matomo as `cip` (defaults to `REMOTE_ADDR`; used for page views and downloads when an auth token is set). Return an empty string to skip IP forwarding.

Download tracking:

* `pm_matomo_tracking_should_rewrite_downloads` — Return `false` to keep original download URLs for the current post.
* `pm_matomo_tracking_is_download_url` — Decide whether a specific URL should be rewritten (receives URL and default extension list).
* `pm_matomo_tracking_download_extensions` — Adjust the list of file extensions that count as downloads.
* `pm_matomo_tracking_download_url` — Customize the generated redirect URL used for download tracking.
* `pm_matomo_tracking_download_redirect_status` — Change the HTTP status code used when redirecting to the original file.

AI assistant bot tracking:

* `pm_matomo_tracking_ai_bot_user_agents` — Extend or replace the list of User-Agent substrings used to detect AI bots.

General:

* `pm_matomo_tracking_log_message` — Listen to debug messages emitted while `WP_DEBUG` is enabled.

=== Example usages ===

    // Skip tracking for administrators.
    add_filter('pm_matomo_tracking_should_track_request', static function ($shouldTrack) {
        return current_user_can('manage_options') ? false : $shouldTrack;
    });

    // Keep original download URLs on the privacy policy page.
    add_filter('pm_matomo_tracking_should_rewrite_downloads', static function ($shouldRewrite) {
        return is_page('privacy-policy') ? false : $shouldRewrite;
    });

    // Force CDN assets to be treated as downloads.
    add_filter('pm_matomo_tracking_is_download_url', static function ($decision, $url) {
        return str_contains($url, 'cdn.example.com/assets/') ? true : $decision;
    }, 10, 2);

    // Add extra file types to download tracking.
    add_filter('pm_matomo_tracking_download_extensions', static function ($extensions) {
        $extensions = array_merge($extensions, ['svg', 'heic']);
        return array_unique($extensions);
    });

    // Append a checksum to rewritten download URLs.
    add_filter('pm_matomo_tracking_download_url', static function ($trackingUrl, $target, $label) {
        $checksum = substr(hash('sha256', $target . $label), 0, 12);
        return add_query_arg('pm_checksum', $checksum, $trackingUrl);
    }, 10, 3);

    // Use a 307 redirect instead of the default 302.
    add_filter('pm_matomo_tracking_download_redirect_status', static function () {
        return 307;
    });

    // Add a custom bot to AI assistant tracking.
    add_filter('pm_matomo_tracking_ai_bot_user_agents', static function (array $substrings): array {
        $substrings[] = 'MyCustomBot';
        return $substrings;
    });

    // Behind a reverse proxy: forward the real client IP from X-Forwarded-For.
    add_filter('pm_matomo_tracking_visitor_ip', static function ($ip, $request) {
        $forwarded = $request->getHeaderLine('X-Forwarded-For');
        if ($forwarded === '') {
            return $ip;
        }

        // Use the first (client) address in the list.
        return trim(explode(',', $forwarded)[0]);
    }, 10, 2);

    // Forward debug messages to the PHP error log while developing.
    add_action('pm_matomo_tracking_log_message', static function ($level, $message) {
        if (!defined('WP_DEBUG') || WP_DEBUG !== true) {
            return;
        }

        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
        error_log(sprintf('[Pagemetrics for Matomo][%s] %s', strtoupper((string) $level), $message));
    }, 10, 2);

== Changelog ==

= 1.1.2 =
* Tested with WordPress 7.1.
* No functional changes.

= 1.1.1 =
* Fixed: the real visitor IP is now forwarded to Matomo as the `cip` parameter when an auth token is set, so page views and downloads geolocate the visitor instead of the WordPress server.
* New `pm_matomo_tracking_visitor_ip` filter to override the forwarded IP (e.g. from a trusted proxy header) or disable IP forwarding.

= 1.1.0 =
* Added AI assistant bot tracking: detects crawls from ChatGPT, Claude, Perplexity and other AI agents and forwards them to Matomo's AI Assistants report (requires Matomo 5.8.0+).
* New `pm_matomo_tracking_ai_bot_user_agents` filter to extend the list of detected bot User-Agents.

= 1.0.0 =
* Initial release with server-side page view tracking, optional download tracking and multisite support.
