Matomo (Piwik) Integration

  • JNext lesson
  • KPrevious lesson
  • FSearch lessons
  • EscClear search

Track redirect clicks as events in Matomo (formerly Piwik) using the HTTP Tracking API. This server-side integration gives you full click analytics in your self-hosted Matomo instance without requiring any client-side JavaScript.

Requirements

  • GT Link Manager 1.5+ installed and active
  • A Matomo instance (self-hosted or cloud)
  • Your Matomo Site ID (Settings > Websites)
  • (Optional) An auth token for enhanced tracking with IP and geo-location (Settings > Personal > Security > Auth tokens)

Installation

  • Add the snippet below to your theme’s functions.php or a site-specific plugin
  • Set GTLM_MATOMO_URL to your Matomo instance URL (no trailing slash)
  • Set GTLM_MATOMO_SITE_ID to your Matomo Site ID
  • (Optional) Set GTLM_MATOMO_TOKEN for IP-based geo-location tracking

The Code

<?php
/**
 * GT Link Manager - Matomo (Piwik) Integration
 *
 * Tracks redirect clicks as events in Matomo via the HTTP Tracking API.
 * Server-side — no JavaScript required.
 *
 * Setup:
 * 1. Set your Matomo instance URL (no trailing slash)
 * 2. Set your Site ID (visible in Matomo under Settings > Websites)
 * 3. (Optional) Set an auth token for enhanced tracking (IP, location)
 *    Get it from Matomo: Settings > Personal > Security > Auth tokens
 *
 * Event category: "Redirect"
 * Event action:   "Link Click"
 * Event name:     Link name or slug
 * Event value:    Redirect HTTP status code
 *
 * @see https://developer.matomo.org/api-reference/tracking-api
 */

defined( 'ABSPATH' ) || exit;

// ── Configuration ────────────────────────────────────────────────────────────
define( 'GTLM_MATOMO_URL',      'https://matomo.example.com' ); // Matomo instance URL (no trailing /)
define( 'GTLM_MATOMO_SITE_ID',  1 );                            // Matomo Site ID
define( 'GTLM_MATOMO_TOKEN',    '' );                            // Auth token (optional, for IP/geo)
// ─────────────────────────────────────────────────────────────────────────────

add_action( 'gtlm_before_redirect', 'gtlm_matomo_track_click', 10, 4 );

/**
 * Send a tracking event to Matomo when a redirect fires.
 *
 * @param array  $link       Link data.
 * @param string $target_url Destination URL.
 * @param int    $status     HTTP status code.
 * @param array  $headers    Response headers.
 */
function gtlm_matomo_track_click( array $link, string $target_url, int $status, array $headers ): void {

	if ( GTLM_MATOMO_URL === 'https://matomo.example.com' ) {
		return; // Not configured yet.
	}

	$request_url = home_url( sanitize_text_field( $_SERVER['REQUEST_URI'] ?? '/' ) );

	$params = [
		// Required.
		'idsite' => GTLM_MATOMO_SITE_ID,
		'rec'    => 1,

		// Page context.
		'url'        => $request_url,
		'urlref'     => sanitize_text_field( $_SERVER['HTTP_REFERER'] ?? '' ),
		'action_name' => 'Redirect: ' . ( $link['name'] ?? $link['slug'] ?? '' ),

		// Event tracking.
		'e_c' => 'Redirect',                                  // Event category
		'e_a' => 'Link Click',                                // Event action
		'e_n' => $link['name'] ?? $link['slug'] ?? 'unknown', // Event name
		'e_v' => $status,                                      // Event value

		// Custom variables (slot 1-5 available).
		'cvar' => wp_json_encode( [
			'1' => [ 'Link Slug', $link['slug'] ?? '' ],
			'2' => [ 'Target URL', mb_substr( $target_url, 0, 200 ) ],
			'3' => [ 'Category ID', (string) ( $link['category_id'] ?? 0 ) ],
		] ),

		// Visitor context.
		'ua'    => sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ?? '' ),
		'lang'  => sanitize_text_field( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '' ),
		'rand'  => wp_rand(),
		'apiv'  => 1,

		// Generate a visitor ID from IP + UA for consistency.
		'_id' => substr( md5( ( $_SERVER['REMOTE_ADDR'] ?? '' ) . ( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 0, 16 ),
	];

	// Add client IP if auth token is set (required for accurate geo-location).
	if ( ! empty( GTLM_MATOMO_TOKEN ) ) {
		$params['token_auth'] = GTLM_MATOMO_TOKEN;
		$client_ip = gtlm_matomo_get_client_ip();
		if ( $client_ip ) {
			$params['cip'] = $client_ip;
		}
	}

	wp_remote_post(
		trailingslashit( GTLM_MATOMO_URL ) . 'matomo.php',
		[
			'body'     => $params,
			'blocking' => false,
			'timeout'  => 1,
		]
	);
}

/**
 * Get the real client IP.
 *
 * @return string|null
 */
function gtlm_matomo_get_client_ip(): ?string {

	$headers = [ 'HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR' ];

	foreach ( $headers as $header ) {
		if ( ! empty( $_SERVER[ $header ] ) ) {
			$ip = strtok( sanitize_text_field( $_SERVER[ $header ] ), ',' );
			if ( filter_var( trim( $ip ), FILTER_VALIDATE_IP ) ) {
				return trim( $ip );
			}
		}
	}

	return null;
}

How It Works

  • Hooks into gtlm_before_redirect to fire on every redirect
  • Sends event tracking data: category = Redirect, action = Link Click, name = link name
  • Uses Matomo custom variables (slots 1-3) for link slug, target URL, and category ID
  • Generates a consistent visitor ID from IP + User Agent for session tracking
  • When an auth token is provided, sends the real client IP for accurate geo-location

Configuration Notes

Events appear in Matomo under Behaviour > Events. You can filter by the event category Redirect to see all link clicks. Custom variables are visible in Visitors > Custom Variables.

The auth token is optional but recommended for accurate geo-location data. Without it, Matomo will use the server’s IP instead of the visitor’s IP for location detection.