updated plugin Connect Matomo version 1.1.5
This commit is contained in:
234
wp-content/plugins/wp-piwik/classes/WP_Piwik/AIBotTracking.php
Normal file
234
wp-content/plugins/wp-piwik/classes/WP_Piwik/AIBotTracking.php
Normal file
@ -0,0 +1,234 @@
|
||||
<?php
|
||||
/**
|
||||
* Matomo - free/libre analytics platform
|
||||
*
|
||||
* @link https://matomo.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
* @package matomo
|
||||
*/
|
||||
|
||||
namespace WP_Piwik;
|
||||
|
||||
use LiteSpeed\ESI;
|
||||
|
||||
/**
|
||||
* Performs server side tracking for AI bots.
|
||||
*
|
||||
* Normal server side tracking: when no caching plugins or CDNs are being
|
||||
* used, this class will send tracking requests in the wp_footer hook.
|
||||
*
|
||||
* When advanced-cache.php is used: when a caching plugin creates an
|
||||
* advanced-cache.php file that WordPress uses, tracking must be done
|
||||
* through the standalone script in misc/track_ai_bot.php. This script
|
||||
* must be manually added to a user's wp-config.php file, right after
|
||||
* ABSPATH is defined.
|
||||
*
|
||||
* When .htaccess is used: when a caching plugin modifies the .htaccess
|
||||
* to serve cached files directly, AI bot tracking is not possible.
|
||||
*
|
||||
* When a CDN is used: when a CDN is used to serve cached content, AI
|
||||
* bot tracking can be accomplished through the use of ESI (Edge Side Includes).
|
||||
* In this case, this class outputs an `<esi:include>` directive that
|
||||
* loads the misc/track_ai_bot.php script. This technique will only work
|
||||
* for CDNs that support ESI.
|
||||
*
|
||||
* The misc/track_ai_bot.php script uses this class without all of WordPress loaded.
|
||||
* It can also be loaded outside of WordPress. Because of this, it is important
|
||||
* that the script and this class use as few total dependencies as possible. Otherwise,
|
||||
* AI bot tracking reduce the performance of requests to cached content.
|
||||
*/
|
||||
class AIBotTracking {
|
||||
|
||||
private static $ai_bot_tracked = false;
|
||||
|
||||
private static $extensions_to_track = array(
|
||||
'', // no extension
|
||||
|
||||
'htm',
|
||||
'html',
|
||||
'php',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* @var Logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var AjaxTracker|null
|
||||
*/
|
||||
private $tracker = null;
|
||||
|
||||
/**
|
||||
* @param Settings $settings
|
||||
* @param Logger $logger
|
||||
*/
|
||||
public function __construct( Settings $settings, Logger $logger ) {
|
||||
$this->settings = $settings;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function register_hooks() {
|
||||
add_action( 'litespeed_init', array( $this, 'litespeed_init' ) );
|
||||
add_action( 'wp_footer', array( $this, 'do_ai_bot_tracking' ), 999999 );
|
||||
}
|
||||
|
||||
public function litespeed_init() {
|
||||
if ( class_exists( ESI::class )
|
||||
&& $this->settings->is_ai_bot_tracking_enabled_via_esi_includes()
|
||||
) {
|
||||
ESI::set_has_esi();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $url
|
||||
* @return void
|
||||
*/
|
||||
public function do_ai_bot_tracking( $url = null ) {
|
||||
// track AI bots only once per request
|
||||
if ( self::$ai_bot_tracked ) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$ai_bot_tracked = true;
|
||||
|
||||
// if using ESI to track, and not within the track_ai_bot.php script, output the appropriate ESI tag
|
||||
$is_using_esi_to_track = $this->settings->is_ai_bot_tracking_enabled_via_esi_includes();
|
||||
if (
|
||||
$is_using_esi_to_track
|
||||
&& empty( $GLOBALS['WP_PIWIK_IN_ESI'] )
|
||||
) {
|
||||
$track_script_url = plugins_url( '/misc/track_ai_bot.php', WP_PIWIK_FILE ) . '?mtm_esi=1&mtm_url=' . rawurlencode( AjaxTracker::getCurrentUrl() );
|
||||
echo '<esi:include src="' . esc_attr( $track_script_url ) . '" cache-control="no-cache" />';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->is_doing_ai_bot_tracking_this_request() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$response_code = http_response_code();
|
||||
$request_elapsed_ms = null;
|
||||
|
||||
// cannot track request time if executed via an esi:include
|
||||
if (
|
||||
empty( $GLOBALS['WP_PIWIK_IN_ESI'] )
|
||||
&& array_key_exists( 'REQUEST_TIME_FLOAT', $_SERVER )
|
||||
) {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
|
||||
$request_elapsed_ms = (int) ( ( microtime( true ) - floatval( $_SERVER['REQUEST_TIME_FLOAT'] ) ) * 1000 );
|
||||
}
|
||||
|
||||
if ( empty( $response_code ) ) {
|
||||
$response_code = 200;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
|
||||
$source = 'WordPress';
|
||||
|
||||
if ( empty( $url ) ) {
|
||||
$url = AjaxTracker::getCurrentUrl();
|
||||
}
|
||||
|
||||
$tracker = $this->get_tracker();
|
||||
|
||||
$tracker->setUrl( $url );
|
||||
|
||||
// cannot count bytes echo'd so no response size tracked
|
||||
$tracker->doTrackPageViewIfAIBot( $response_code, null, $request_elapsed_ms, $source );
|
||||
}
|
||||
|
||||
public function should_track_current_page() {
|
||||
if ( is_admin() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( wp_doing_ajax() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $_SERVER['REQUEST_URI'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$request_path = (string) wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH );
|
||||
|
||||
if ( preg_match( '/matomo\.php$/', $request_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->is_request_for_file( $request_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_request_for_file( $request_path ) {
|
||||
if (
|
||||
! empty( $_SERVER['DOCUMENT_ROOT'] )
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
&& is_dir( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) . $request_path )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$extension = pathinfo( $request_path, PATHINFO_EXTENSION );
|
||||
return ! in_array( $extension, self::$extensions_to_track, true );
|
||||
}
|
||||
|
||||
public function is_js_execution_detected() {
|
||||
return ! empty( $_COOKIE['matomo_has_js'] )
|
||||
&& '1' === $_COOKIE['matomo_has_js'];
|
||||
}
|
||||
|
||||
private function is_doing_ai_bot_tracking_this_request() {
|
||||
if ( ! empty( $GLOBALS['WP_PIWIK_IN_ESI'] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! $this->should_track_current_page() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->is_js_execution_detected() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tracker = $this->get_tracker();
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
if ( ! AjaxTracker::isUserAgentAIBot( $tracker->userAgent ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
! $this->settings->is_ai_bot_tracking_enabled()
|
||||
|| ! $this->settings->is_tracking_enabled()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function get_tracker() {
|
||||
if ( empty( $this->tracker ) ) {
|
||||
$this->tracker = new AjaxTracker( $this->settings, $this->logger );
|
||||
$this->tracker->setRequestTimeout( 1 );
|
||||
}
|
||||
|
||||
return $this->tracker;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user