Navigate privacy laws with feline precision — detect every boundary, respect every territory! GDPR compliance and privacy protection for WordPress. - Cookie consent management - Privacy boundary detection - GDPR-compliant analytics gating - Cross-plugin consent coordination (integrates with TigerStyle Heat) - Visitor preference tracking - Configurable cookie categories Includes build.sh and .distignore for WordPress-installable release ZIPs.
421 lines
14 KiB
PHP
421 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* TigerStyle Whiskers Analytics Integration
|
|
*
|
|
* Bridge privacy consent with analytics - let Heat know when the coast is clear!
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class TigerStyleWhiskers_AnalyticsIntegration {
|
|
|
|
/**
|
|
* Single instance
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Analytics providers
|
|
*/
|
|
private $providers = array();
|
|
|
|
/**
|
|
* Get instance
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$instance)) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
$this->init_analytics_integration();
|
|
}
|
|
|
|
/**
|
|
* Initialize analytics integration
|
|
*/
|
|
private function init_analytics_integration() {
|
|
$this->define_providers();
|
|
|
|
// Hook into consent events
|
|
add_action('tigerstyle_whiskers_consent_granted', array($this, 'handle_consent_granted'), 10, 2);
|
|
add_action('tigerstyle_whiskers_consent_withdrawn', array($this, 'handle_consent_withdrawn'), 10, 2);
|
|
|
|
// Integration with TigerStyle Heat
|
|
add_action('wp_head', array($this, 'inject_consent_bridge'), 1);
|
|
|
|
// Admin hooks
|
|
if (is_admin()) {
|
|
add_action('wp_ajax_whiskers_test_analytics_integration', array($this, 'ajax_test_integration'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Define analytics providers
|
|
*/
|
|
private function define_providers() {
|
|
$this->providers = array(
|
|
'google_analytics' => array(
|
|
'name' => __('Google Analytics', 'tigerstyle-whiskers'),
|
|
'consent_category' => 'analytics',
|
|
'script_pattern' => '/gtag|analytics\.js|ga\.js/',
|
|
'cookie_patterns' => array('_ga', '_gid', '_gat'),
|
|
'integration_class' => 'TigerStyleSEO' // Heat integration
|
|
),
|
|
'google_tag_manager' => array(
|
|
'name' => __('Google Tag Manager', 'tigerstyle-whiskers'),
|
|
'consent_category' => 'analytics',
|
|
'script_pattern' => '/googletagmanager\.com/',
|
|
'cookie_patterns' => array('_ga', '_gid', '_gat'),
|
|
'integration_class' => 'TigerStyleSEO'
|
|
),
|
|
'facebook_pixel' => array(
|
|
'name' => __('Facebook Pixel', 'tigerstyle-whiskers'),
|
|
'consent_category' => 'marketing',
|
|
'script_pattern' => '/connect\.facebook\.net/',
|
|
'cookie_patterns' => array('_fbp', '_fbc', 'fr'),
|
|
'integration_class' => null
|
|
),
|
|
'hotjar' => array(
|
|
'name' => __('Hotjar', 'tigerstyle-whiskers'),
|
|
'consent_category' => 'analytics',
|
|
'script_pattern' => '/static\.hotjar\.com/',
|
|
'cookie_patterns' => array('_hjid', '_hjSession'),
|
|
'integration_class' => null
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handle consent granted
|
|
*/
|
|
public function handle_consent_granted($consent_data, $user_info) {
|
|
foreach ($this->providers as $provider_id => $provider) {
|
|
$category = $provider['consent_category'];
|
|
|
|
if (isset($consent_data[$category]) && $consent_data[$category]) {
|
|
$this->enable_provider($provider_id, $provider);
|
|
}
|
|
}
|
|
|
|
// Trigger Heat integration if analytics consent granted
|
|
if (isset($consent_data['analytics']) && $consent_data['analytics']) {
|
|
$this->trigger_heat_integration(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle consent withdrawn
|
|
*/
|
|
public function handle_consent_withdrawn($consent_categories, $user_info) {
|
|
foreach ($consent_categories as $category) {
|
|
foreach ($this->providers as $provider_id => $provider) {
|
|
if ($provider['consent_category'] === $category) {
|
|
$this->disable_provider($provider_id, $provider);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Disable Heat integration if analytics consent withdrawn
|
|
if (in_array('analytics', $consent_categories)) {
|
|
$this->trigger_heat_integration(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enable analytics provider
|
|
*/
|
|
private function enable_provider($provider_id, $provider) {
|
|
// Log the enabling
|
|
do_action('tigerstyle_whiskers_analytics_enabled', $provider_id, $provider);
|
|
|
|
// Provider-specific enabling logic
|
|
switch ($provider_id) {
|
|
case 'google_analytics':
|
|
$this->enable_google_analytics();
|
|
break;
|
|
case 'google_tag_manager':
|
|
$this->enable_google_tag_manager();
|
|
break;
|
|
case 'facebook_pixel':
|
|
$this->enable_facebook_pixel();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable analytics provider
|
|
*/
|
|
private function disable_provider($provider_id, $provider) {
|
|
// Clear provider cookies
|
|
$this->clear_provider_cookies($provider['cookie_patterns']);
|
|
|
|
// Log the disabling
|
|
do_action('tigerstyle_whiskers_analytics_disabled', $provider_id, $provider);
|
|
|
|
// Provider-specific disabling logic
|
|
switch ($provider_id) {
|
|
case 'google_analytics':
|
|
$this->disable_google_analytics();
|
|
break;
|
|
case 'google_tag_manager':
|
|
$this->disable_google_tag_manager();
|
|
break;
|
|
case 'facebook_pixel':
|
|
$this->disable_facebook_pixel();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear provider cookies
|
|
*/
|
|
private function clear_provider_cookies($cookie_patterns) {
|
|
foreach ($cookie_patterns as $pattern) {
|
|
// Use JavaScript to clear cookies client-side
|
|
$this->add_cookie_clear_script($pattern);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add cookie clearing script
|
|
*/
|
|
private function add_cookie_clear_script($cookie_pattern) {
|
|
add_action('wp_footer', function() use ($cookie_pattern) {
|
|
echo "<script>
|
|
(function() {
|
|
var cookies = document.cookie.split(';');
|
|
for (var i = 0; i < cookies.length; i++) {
|
|
var cookie = cookies[i].trim();
|
|
var name = cookie.split('=')[0];
|
|
if (name.indexOf('{$cookie_pattern}') === 0) {
|
|
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=' + window.location.hostname;
|
|
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/';
|
|
}
|
|
}
|
|
})();
|
|
</script>";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Enable Google Analytics
|
|
*/
|
|
private function enable_google_analytics() {
|
|
// Trigger Heat to enable GA if it's managing it
|
|
if (class_exists('TigerStyleSEO')) {
|
|
do_action('tigerstyle_heat_enable_analytics');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable Google Analytics
|
|
*/
|
|
private function disable_google_analytics() {
|
|
// Trigger Heat to disable GA
|
|
if (class_exists('TigerStyleSEO')) {
|
|
do_action('tigerstyle_heat_disable_analytics');
|
|
}
|
|
|
|
// Disable GA tracking
|
|
add_action('wp_footer', function() {
|
|
echo "<script>
|
|
if (typeof gtag !== 'undefined') {
|
|
gtag('consent', 'update', {
|
|
'analytics_storage': 'denied'
|
|
});
|
|
}
|
|
if (typeof ga !== 'undefined') {
|
|
ga('set', 'anonymizeIp', true);
|
|
ga('set', 'allowAdFeatures', false);
|
|
}
|
|
</script>";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Enable Google Tag Manager
|
|
*/
|
|
private function enable_google_tag_manager() {
|
|
add_action('wp_footer', function() {
|
|
echo "<script>
|
|
if (typeof dataLayer !== 'undefined') {
|
|
dataLayer.push({
|
|
'event': 'consent_granted',
|
|
'consent_analytics': true
|
|
});
|
|
}
|
|
</script>";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Disable Google Tag Manager
|
|
*/
|
|
private function disable_google_tag_manager() {
|
|
add_action('wp_footer', function() {
|
|
echo "<script>
|
|
if (typeof dataLayer !== 'undefined') {
|
|
dataLayer.push({
|
|
'event': 'consent_withdrawn',
|
|
'consent_analytics': false
|
|
});
|
|
}
|
|
</script>";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Enable Facebook Pixel
|
|
*/
|
|
private function enable_facebook_pixel() {
|
|
add_action('wp_footer', function() {
|
|
echo "<script>
|
|
if (typeof fbq !== 'undefined') {
|
|
fbq('consent', 'grant');
|
|
}
|
|
</script>";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Disable Facebook Pixel
|
|
*/
|
|
private function disable_facebook_pixel() {
|
|
add_action('wp_footer', function() {
|
|
echo "<script>
|
|
if (typeof fbq !== 'undefined') {
|
|
fbq('consent', 'revoke');
|
|
}
|
|
</script>";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Trigger Heat integration
|
|
*/
|
|
private function trigger_heat_integration($enable) {
|
|
if (class_exists('TigerStyleSEO')) {
|
|
if ($enable) {
|
|
do_action('tigerstyle_whiskers_heat_consent_granted');
|
|
} else {
|
|
do_action('tigerstyle_whiskers_heat_consent_withdrawn');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inject consent bridge script
|
|
*/
|
|
public function inject_consent_bridge() {
|
|
$consent_state = $this->get_current_consent_state();
|
|
|
|
echo "<script>
|
|
window.tigerstyleWhiskersConsent = {
|
|
hasAnalyticsConsent: function() {
|
|
return " . ($consent_state['analytics'] ? 'true' : 'false') . ";
|
|
},
|
|
hasMarketingConsent: function() {
|
|
return " . ($consent_state['marketing'] ? 'true' : 'false') . ";
|
|
},
|
|
getConsentState: function() {
|
|
return " . wp_json_encode($consent_state) . ";
|
|
}
|
|
};
|
|
|
|
// Fire consent state event for other scripts
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var event = new CustomEvent('tigerstyleWhiskersConsentReady', {
|
|
detail: window.tigerstyleWhiskersConsent.getConsentState()
|
|
});
|
|
document.dispatchEvent(event);
|
|
});
|
|
</script>";
|
|
}
|
|
|
|
/**
|
|
* Get current consent state
|
|
*/
|
|
private function get_current_consent_state() {
|
|
$cookie_consent = tigerstyle_whiskers()->get_whisker('cookie_consent');
|
|
|
|
if ($cookie_consent && method_exists($cookie_consent, 'get_consent_state')) {
|
|
return $cookie_consent->get_consent_state();
|
|
}
|
|
|
|
// Default state
|
|
return array(
|
|
'necessary' => true,
|
|
'analytics' => false,
|
|
'marketing' => false,
|
|
'preferences' => false
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get integration status
|
|
*/
|
|
public function get_integration_status() {
|
|
$status = array();
|
|
|
|
foreach ($this->providers as $provider_id => $provider) {
|
|
$status[$provider_id] = array(
|
|
'name' => $provider['name'],
|
|
'category' => $provider['consent_category'],
|
|
'detected' => $this->is_provider_detected($provider),
|
|
'consent_required' => true,
|
|
'current_consent' => $this->has_consent_for_category($provider['consent_category']),
|
|
'integration_class' => $provider['integration_class'],
|
|
'heat_integrated' => ($provider['integration_class'] === 'TigerStyleSEO' && class_exists('TigerStyleSEO'))
|
|
);
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Check if provider is detected on the site
|
|
*/
|
|
private function is_provider_detected($provider) {
|
|
// This would need actual detection logic
|
|
// For now, return true for Heat integration
|
|
return $provider['integration_class'] === 'TigerStyleSEO' && class_exists('TigerStyleSEO');
|
|
}
|
|
|
|
/**
|
|
* Check if user has consent for category
|
|
*/
|
|
private function has_consent_for_category($category) {
|
|
$consent_state = $this->get_current_consent_state();
|
|
return isset($consent_state[$category]) ? $consent_state[$category] : false;
|
|
}
|
|
|
|
/**
|
|
* AJAX: Test analytics integration
|
|
*/
|
|
public function ajax_test_integration() {
|
|
check_ajax_referer('whiskers_admin_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions', 'tigerstyle-whiskers'));
|
|
}
|
|
|
|
$integration_status = $this->get_integration_status();
|
|
$heat_active = class_exists('TigerStyleSEO');
|
|
|
|
wp_send_json_success(array(
|
|
'message' => __('Analytics integration test completed!', 'tigerstyle-whiskers'),
|
|
'heat_active' => $heat_active,
|
|
'providers' => $integration_status,
|
|
'consent_bridge_active' => true
|
|
));
|
|
}
|
|
} |