PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.14.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.14.2
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / classes / WpMatomo / TrackingCode.php
matomo / classes / WpMatomo Last commit date
Admin 3 years ago Commands 4 years ago Db 4 years ago Ecommerce 3 years ago Report 4 years ago Site 3 years ago TrackingCode 4 years ago Updater 4 years ago User 3 years ago WpStatistics 4 years ago views 4 years ago API.php 4 years ago Access.php 4 years ago AjaxTracker.php 5 years ago Annotations.php 4 years ago Bootstrap.php 4 years ago Capabilities.php 4 years ago Compatibility.php 4 years ago Email.php 4 years ago Installer.php 4 years ago Logger.php 4 years ago OptOut.php 4 years ago Paths.php 4 years ago PrivacyBadge.php 4 years ago RedirectOnActivation.php 4 years ago Referral.php 4 years ago Roles.php 4 years ago ScheduledTasks.php 4 years ago Settings.php 4 years ago Site.php 3 years ago TrackingCode.php 4 years ago Uninstaller.php 4 years ago Updater.php 4 years ago User.php 4 years ago
TrackingCode.php
227 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 * @package matomo
8 */
9
10 namespace WpMatomo;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // if accessed directly
14 }
15
16 use WpMatomo\TrackingCode\TrackingCodeGenerator;
17 use WpMatomo\Settings;
18
19 class TrackingCode {
20
21 /**
22 * @var Settings
23 */
24 private $settings;
25
26 /**
27 * @var Logger
28 */
29 private $logger;
30
31 /**
32 * @var TrackingCodeGenerator
33 */
34 private $generator;
35
36 /**
37 * @param Settings $settings
38 */
39 public function __construct( $settings ) {
40 $this->settings = $settings;
41 $this->logger = new Logger();
42 $this->generator = new TrackingCodeGenerator( $this->settings );
43 $this->generator->register_hooks();
44 }
45
46 public function register_hooks() {
47 if ( $this->settings->is_tracking_enabled() ) {
48 if ( $this->settings->is_track_feed() ) {
49 add_filter( 'the_excerpt_rss', [ $this, 'add_feed_tracking' ] );
50 add_filter( 'the_content', [ $this, 'add_feed_tracking' ] );
51 }
52 if ( $this->settings->is_add_feed_campaign() ) {
53 add_filter( 'post_link', [ $this, 'add_feed_campaign' ] );
54 }
55 if ( $this->settings->is_cross_domain_linking_enabled() ) {
56 add_filter( 'wp_redirect', [ $this, 'forward_cross_domain_visitor_id' ] );
57 }
58
59 $is_admin = is_admin() || ! empty( $GLOBALS['MATOMO_LOADED_DIRECTLY'] );
60
61 if ( ! $is_admin || $this->settings->is_admin_tracking_enabled() ) {
62 $prefix = 'wp';
63 if ( $is_admin ) {
64 $prefix = 'admin';
65 }
66
67 $position = $prefix . '_head';
68 if ( $this->settings->get_tracking_code_position() === 'footer' ) {
69 $position = $prefix . '_footer';
70 }
71
72 add_action( $position, [ $this, 'add_javascript_code' ] );
73
74 if ( $this->settings->is_add_no_script_code() ) {
75 add_action( $prefix . '_footer', [ $this, 'add_noscript_code' ] );
76 }
77 }
78 }
79 }
80
81 /**
82 * Check if user should not be tracked
83 *
84 * @return boolean Do not track user?
85 */
86 public function is_hidden_user() {
87 if ( is_multisite() && is_super_admin() ) {
88 // by pass the hook in the WP_User::has_cap method which bypass the capabilities management
89 $stealth = $this->settings->get_global_option( Settings::OPTION_KEY_STEALTH );
90 return ( ! empty( $stealth['administrator'] ) );
91 }
92 return current_user_can( Capabilities::KEY_STEALTH );
93 }
94
95 /**
96 * Echo javascript tracking code
97 */
98 public function add_javascript_code() {
99 if ( $this->is_hidden_user() ) {
100 $this->logger->log( 'Do not add tracking code to site (user should not be tracked) Blog ID: ' . get_current_blog_id(), Logger::LEVEL_DEBUG );
101
102 return;
103 }
104
105 $tracking_code = $this->generator->get_tracking_code();
106
107 $this->logger->log( 'Add tracking code. Blog ID: ' . get_current_blog_id(), Logger::LEVEL_DEBUG );
108
109 if ( $this->settings->is_network_enabled()
110 && 'manually' === $this->settings->get_global_option( 'track_mode' ) ) {
111 $site = new Site();
112 $site_id = $site->get_current_matomo_site_id();
113 if ( $site_id ) {
114 $tracking_code = str_replace( '{MATOMO_API_ENDPOINT}', wp_json_encode( $this->generator->get_tracker_endpoint() ), $tracking_code );
115 $tracking_code = str_replace( '{MATOMO_JS_ENDPOINT}', wp_json_encode( $this->generator->get_js_endpoint() ), $tracking_code );
116 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
117 echo str_replace( '{MATOMO_IDSITE}', $site_id, $tracking_code );
118 } else {
119 echo '<!-- Site not yet synced with Matomo, tracking code will be added later -->';
120 }
121 } else {
122 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
123 echo $tracking_code;
124 }
125 }
126
127 /**
128 * Echo noscript tracking code
129 */
130 public function add_noscript_code() {
131 if ( $this->is_hidden_user() ) {
132 $this->logger->log( 'Do not add noscript code to site (user should not be tracked) Blog ID: ' . get_current_blog_id(), Logger::LEVEL_DEBUG );
133
134 return;
135 }
136
137 $code = $this->generator->get_noscript_code();
138
139 if ( ! empty( $code ) ) {
140 $this->logger->log( 'Add noscript code. Blog ID: ' . get_current_blog_id(), Logger::LEVEL_DEBUG );
141 $contains_noscript_tag = stripos( $code, '<noscript' ) !== false;
142 if ( ! $contains_noscript_tag ) {
143 echo '<noscript>';
144 }
145 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
146 echo $code;
147 if ( ! $contains_noscript_tag ) {
148 echo '</noscript>';
149 }
150 echo "\n";
151 } else {
152 $this->logger->log( 'No noscript code present. Blog ID: ' . get_current_blog_id(), Logger::LEVEL_DEBUG );
153 }
154 }
155
156 /**
157 * Add a campaign parameter to feed permalink
158 *
159 * @param string $permalink
160 * permalink
161 *
162 * @return string permalink extended by campaign parameter
163 */
164 public function add_feed_campaign( $permalink ) {
165 global $post;
166 if ( is_feed() && ! empty( $post ) ) {
167 $this->logger->log( 'Add campaign to feed permalink.' );
168 $sep = ( strpos( $permalink, '?' ) === false ? '?' : '&' );
169 $permalink .= $sep . 'pk_campaign=' . rawurlencode( $this->settings->get_global_option( 'track_feed_campaign' ) ) . '&pk_kwd=' . rawurlencode( $post->post_name );
170 }
171
172 return $permalink;
173 }
174
175 /**
176 * Add tracking pixels to feed content
177 *
178 * @param string $content
179 * post content
180 *
181 * @return string post content extended by tracking pixel
182 */
183 public function add_feed_tracking( $content ) {
184 global $post;
185 if ( is_feed() ) {
186 $this->logger->log( 'Add tracking image to feed entry.' );
187 $site = new Site();
188 $site_id = $site->get_current_matomo_site_id();
189 if ( ! $site_id ) {
190 return false;
191 }
192 $title = the_title( null, null, false );
193 $posturl = get_permalink( $post->ID );
194 $urlref = get_bloginfo( 'rss2_url' );
195
196 $tracker_endpoint = $this->generator->get_tracker_endpoint();
197
198 $tracking_image = $tracker_endpoint . '?idsite=' . $site_id . '&amp;rec=1&amp;url=' . rawurlencode( $posturl ) . '&amp;action_name=' . rawurlencode( $title ) . '&amp;urlref=' . rawurlencode( $urlref );
199 $content .= '<img src="' . $tracking_image . '" style="border:0;width:0;height:0" width="0" height="0" alt="" />';
200 }
201
202 return $content;
203 }
204
205 /**
206 * Forwards the cross domain parameter pk_vid if the URL parameter is set and a user is about to be redirected.
207 * When another website links to WooCommerce with a pk_vid parameter, and WooCommerce redirects the user to another
208 * URL, the pk_vid parameter would get lost and the visitorId would later not be applied by the tracking code
209 * due to the lost pk_vid URL parameter. If the URL parameter is set, we make sure to forward this parameter.
210 *
211 * @param string $location
212 *
213 * @return string location extended by pk_vid URL parameter if the URL parameter is set
214 */
215 public function forward_cross_domain_visitor_id( $location ) {
216 if ( ! empty( $_GET['pk_vid'] ) ) {
217 $pk_vid = sanitize_text_field( wp_unslash( $_GET['pk_vid'] ) );
218 if ( preg_match( '/^[a-zA-Z0-9]{24,60}$/', $pk_vid ) ) {
219 // currently, the pk_vid parameter is 32 characters long, but it may vary over time.
220 $location = add_query_arg( 'pk_vid', $pk_vid, $location );
221 }
222 }
223
224 return $location;
225 }
226 }
227