updated wp plugin

This commit is contained in:
Karl Breuer 2025-04-07 17:14:25 +02:00
parent 1e49d1bd76
commit 484426499b
3 changed files with 394 additions and 35 deletions

133
wordpress/block.js Normal file
View File

@ -0,0 +1,133 @@
/**
* Tracking Block for Gutenberg with Popup Editor
*/
(function(blocks, element, blockEditor) {
var el = element.createElement;
var InnerBlocks = blockEditor.InnerBlocks;
var useBlockProps = blockEditor.useBlockProps;
var __ = wp.i18n.__;
var Button = wp.components.Button;
var Popover = wp.components.Popover;
var TextControl = wp.components.TextControl;
var useState = wp.element.useState;
blocks.registerBlockType('simplified-tracking/track-element', {
title: 'Tracking Wrapper',
icon: 'chart-bar',
category: 'design',
attributes: {
eventName: {
type: 'string',
default: 'tracked_element'
}
},
edit: function(props) {
var blockProps = useBlockProps();
var eventName = props.attributes.eventName;
var [isPopoverVisible, setPopoverVisible] = useState(false);
function onChangeEventName(newEventName) {
props.setAttributes({ eventName: newEventName });
}
return el(
'div',
blockProps,
el(
'div',
{ className: 'tracking-block-wrapper' },
el(
'div',
{ className: 'tracking-block-notice' },
'Event: ' + eventName,
el(
Button,
{
isSmall: true,
onClick: function() {
setPopoverVisible(!isPopoverVisible);
},
style: {
marginLeft: '8px',
background: 'white',
color: '#007cba'
}
},
'Edit'
),
isPopoverVisible && el(
Popover,
{
onClose: function() {
setPopoverVisible(false);
},
position: 'bottom',
focusOnMount: 'firstElement'
},
el(
'div',
{
style: {
padding: '16px',
width: '300px'
}
},
el(
'h3',
{
style: {
margin: '0 0 8px 0'
}
},
'Tracking Event Settings'
),
el(
TextControl,
{
label: 'Event Name',
value: eventName,
onChange: onChangeEventName,
help: 'Enter the event name to track when this element is clicked'
}
),
el(
Button,
{
isPrimary: true,
onClick: function() {
setPopoverVisible(false);
}
},
'Done'
)
)
)
),
el(
'div',
{ style: { marginTop: '5px' } },
el(InnerBlocks)
)
)
);
},
save: function(props) {
var blockProps = useBlockProps.save({
className: 'tracking-block-wrapper',
onClick: "tE('" + props.attributes.eventName + "')"
});
return el(
'div',
blockProps,
el(InnerBlocks.Content)
);
}
});
}(
window.wp.blocks,
window.wp.element,
window.wp.blockEditor
));

View File

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Plugin Name: Simple Tracking Plugin * Plugin Name: Simplified Tracking Plugin
* Description: Adds tracking script to website header and forwards tracking data to external service * Description: Adds tracking script to website header and tracks user interactions
* Version: 1.0.0 * Version: 1.2.0
* Author: Karl Breuer * Author: Karl Breuer
* Text Domain: simple-tracking * Text Domain: simple-tracking
*/ */
@ -12,7 +12,7 @@ if (!defined('ABSPATH')) {
exit; exit;
} }
class Simple_Tracking_Plugin { class Simplified_Tracking_Plugin {
// Plugin instance // Plugin instance
private static $instance = null; private static $instance = null;
@ -33,6 +33,15 @@ class Simple_Tracking_Plugin {
// Add settings page // Add settings page
add_action('admin_menu', array($this, 'add_settings_page')); add_action('admin_menu', array($this, 'add_settings_page'));
add_action('admin_init', array($this, 'register_settings')); add_action('admin_init', array($this, 'register_settings'));
// Add focused tracking for elements with specific classes
add_action('wp_footer', array($this, 'add_class_tracking_script'), 99);
// Add shortcode for manual tracking
add_shortcode('track_element', array($this, 'tracking_shortcode'));
// Register custom block for Gutenberg
add_action('init', array($this, 'register_tracking_block'));
} }
/** /**
@ -58,9 +67,6 @@ class Simple_Tracking_Plugin {
// Initialize tracking function // Initialize tracking function
function tE(eventName, additionalParams = {}) { function tE(eventName, additionalParams = {}) {
// Create tracking data object // Create tracking data object
console.log(eventName)
const data = { const data = {
event: eventName, event: eventName,
url: window.location.href, url: window.location.href,
@ -70,7 +76,8 @@ function tE(eventName, additionalParams = {}) {
lang: navigator.language || navigator.userLanguage, lang: navigator.language || navigator.userLanguage,
}; };
console.log(data) // Add any additional parameters
Object.assign(data, additionalParams);
// Helper function to serialize an object into URL parameters // Helper function to serialize an object into URL parameters
function serializeObject(obj, prefix) { function serializeObject(obj, prefix) {
@ -89,14 +96,12 @@ function tE(eventName, additionalParams = {}) {
return str.join("&"); return str.join("&");
} }
// Function for sending tracking data
// Function for fallback methods
function sendInfo() { function sendInfo() {
try { try {
// Send to our WordPress endpoint first, which will forward to the tracking server // Send to our WordPress endpoint first, which will forward to the tracking server
const siteUrl = window.location.origin; const siteUrl = window.location.origin;
const trackingUrl = `${siteUrl}/track?${serializeObject(data)}`; const trackingUrl = `${siteUrl}/track?${serializeObject(data)}`;
console.log(trackingUrl)
fetch(trackingUrl, { fetch(trackingUrl, {
method: "POST", method: "POST",
mode: "no-cors", mode: "no-cors",
@ -109,11 +114,10 @@ function tE(eventName, additionalParams = {}) {
}); });
return true; return true;
} catch (e) { } catch (e) {
console.log(e) console.error("Tracking error:", e);
} }
} }
// No sendBeacon support, use fallbacks
return sendInfo(); return sendInfo();
} }
</script> </script>
@ -123,13 +127,175 @@ document.addEventListener("DOMContentLoaded", function() {
try { try {
tE("pageload"); tE("pageload");
} catch (error) { } catch (error) {
console.error("Error in DOMContentLoaded:", error); console.error("Error in page load tracking:", error);
} }
}); });
</script> </script>
<?php <?php
} }
/**
* Add JavaScript to track elements with specific classes
*/
public function add_class_tracking_script() {
// Get custom elements to track
$track_classes = get_option('simple_tracking_track_classes', '');
$track_classes_array = array_filter(array_map('trim', explode(',', $track_classes)));
if (empty($track_classes_array)) {
return;
}
?>
<!-- Simplified class-based tracking script -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Helper function to get element details for tracking
function getElementDetails(element) {
const details = {};
// Get element text or alternative
if (element.textContent && element.textContent.trim()) {
details.text = element.textContent.trim();
} else if (element.placeholder) {
details.text = element.placeholder;
} else if (element.value) {
details.text = element.value;
} else if (element.alt) {
details.text = element.alt;
} else if (element.getAttribute('aria-label')) {
details.text = element.getAttribute('aria-label');
}
// Limit text length
if (details.text && details.text.length > 50) {
details.text = details.text.substring(0, 47) + '...';
}
// Get element ID, class and href if available
if (element.id) {
details.id = element.id;
}
if (element.className) {
details.class = element.className;
}
if (element.href) {
const href = element.href;
// Only include if it's not too long
if (href.length < 100) {
details.href = href;
}
}
return details;
}
<?php foreach ($track_classes_array as $class) : ?>
// Track elements with class: <?php echo esc_js($class); ?>
const <?php echo str_replace('-', '_', sanitize_key($class)); ?>Elements = document.querySelectorAll('.<?php echo esc_js($class); ?>');
<?php echo str_replace('-', '_', sanitize_key($class)); ?>Elements.forEach(function(element) {
element.addEventListener('click', function(e) {
const details = getElementDetails(element);
tE('custom_element_click', { element: 'custom', class: '<?php echo esc_js($class); ?>', ...details });
});
});
<?php endforeach; ?>
// Track elements with data-track attribute
const trackedElements = document.querySelectorAll('[data-track]');
trackedElements.forEach(function(element) {
element.addEventListener('click', function(e) {
const eventName = element.getAttribute('data-track') || 'tracked_element';
const details = getElementDetails(element);
tE(eventName, { element: 'data-track', ...details });
});
});
});
</script>
<?php
}
/**
* Shortcode for tracking elements
*/
public function tracking_shortcode($atts, $content = null) {
$atts = shortcode_atts(array(
'event' => 'tracked_element',
'class' => '',
'style' => '',
), $atts, 'track_element');
// Sanitize attributes
$event = esc_attr($atts['event']);
$class = esc_attr($atts['class']);
$style = esc_attr($atts['style']);
// Return the div with content and onclick attribute
return sprintf(
'<div class="tracking-wrapper %s" style="%s" onclick="tE(\'%s\')">%s</div>',
$class,
$style,
$event,
do_shortcode($content)
);
}
/**
* Register Gutenberg tracking block
*/
public function register_tracking_block() {
// Only register block if Gutenberg is available
if (!function_exists('register_block_type')) {
return;
}
// Register block script
wp_register_script(
'tracking-block-editor',
plugins_url('block.js', __FILE__),
array(
'wp-blocks',
'wp-element',
'wp-block-editor',
'wp-components',
'wp-i18n'
),
filemtime(plugin_dir_path(__FILE__) . 'block.js')
);
// Register block styles
wp_register_style(
'tracking-block-editor-style',
plugins_url('block.css', __FILE__),
array(),
filemtime(plugin_dir_path(__FILE__) . 'tracking-block.css')
);
// Register the block
register_block_type('simplified-tracking/track-element', array(
'editor_script' => 'tracking-block-editor',
'editor_style' => 'tracking-block-editor-style',
'attributes' => array(
'eventName' => array(
'type' => 'string',
'default' => 'tracked_element',
),
),
));
// Add inline script to ensure tE function is available in editor
wp_add_inline_script('tracking-block-editor', "
// Mock tE function for the editor if it doesn't exist
if (typeof window.tE === 'undefined') {
window.tE = function(eventName) {
console.log('Tracking event: ' + eventName);
};
}
");
}
/** /**
* Register tracking endpoint * Register tracking endpoint
*/ */
@ -150,11 +316,6 @@ document.addEventListener("DOMContentLoaded", function() {
*/ */
public function handle_tracking_request($wp) { public function handle_tracking_request($wp) {
if (isset($wp->query_vars['tracking_endpoint'])) { if (isset($wp->query_vars['tracking_endpoint'])) {
// Log that we received a tracking request
error_log('Simple Tracking Plugin: Tracking request received');
// Log the query parameters
error_log('Simple Tracking Plugin: Query params: ' . print_r($_GET, true));
$this->forward_to_tracker(); $this->forward_to_tracker();
exit; exit;
} }
@ -168,14 +329,6 @@ document.addEventListener("DOMContentLoaded", function() {
$tracking_server_url = get_option('simple_tracking_server_url', $this->tracking_server_url); $tracking_server_url = get_option('simple_tracking_server_url', $this->tracking_server_url);
$forward_url = 'https://' . $tracking_server_url . '/spur'; $forward_url = 'https://' . $tracking_server_url . '/spur';
// Log the request (for debugging)
error_log('Forwarding tracking request to: ' . $forward_url);
error_log('Simple Tracking Plugin: Request method: ' . $_SERVER['REQUEST_METHOD']);
// Create a new cURL resource // Create a new cURL resource
$ch = curl_init(); $ch = curl_init();
@ -203,7 +356,6 @@ document.addEventListener("DOMContentLoaded", function() {
// If a custom destination is provided in the header, use it // If a custom destination is provided in the header, use it
$forward_url = 'https://' . $value . '/spur'; $forward_url = 'https://' . $value . '/spur';
curl_setopt($ch, CURLOPT_URL, $forward_url . '?' . $query_string); curl_setopt($ch, CURLOPT_URL, $forward_url . '?' . $query_string);
error_log('Overriding destination with: ' . $value);
} }
$headers[] = "$name: $value"; $headers[] = "$name: $value";
} }
@ -214,7 +366,6 @@ document.addEventListener("DOMContentLoaded", function() {
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) { if (curl_errno($ch)) {
error_log('cURL error: ' . curl_error($ch));
$http_code = 500; $http_code = 500;
} }
@ -273,6 +424,7 @@ document.addEventListener("DOMContentLoaded", function() {
*/ */
public function register_settings() { public function register_settings() {
register_setting('simple_tracking_settings', 'simple_tracking_server_url'); register_setting('simple_tracking_settings', 'simple_tracking_server_url');
register_setting('simple_tracking_settings', 'simple_tracking_track_classes');
add_settings_section( add_settings_section(
'simple_tracking_section', 'simple_tracking_section',
@ -288,6 +440,21 @@ document.addEventListener("DOMContentLoaded", function() {
'simple-tracking-settings', 'simple-tracking-settings',
'simple_tracking_section' 'simple_tracking_section'
); );
add_settings_section(
'simple_tracking_auto_section',
'Element Tracking Settings',
array($this, 'auto_settings_section_callback'),
'simple-tracking-settings'
);
add_settings_field(
'simple_tracking_track_classes',
'Track Elements with Classes',
array($this, 'track_classes_callback'),
'simple-tracking-settings',
'simple_tracking_auto_section'
);
} }
/** /**
@ -297,6 +464,13 @@ document.addEventListener("DOMContentLoaded", function() {
echo '<p>Configure your tracking server settings.</p>'; echo '<p>Configure your tracking server settings.</p>';
} }
/**
* Auto tracking settings section callback
*/
public function auto_settings_section_callback() {
echo '<p>Configure which elements to track based on CSS classes.</p>';
}
/** /**
* Server URL field callback * Server URL field callback
*/ */
@ -305,7 +479,15 @@ document.addEventListener("DOMContentLoaded", function() {
echo '<input type="text" id="simple_tracking_server_url" name="simple_tracking_server_url" value="' . esc_attr($value) . '" class="regular-text">'; echo '<input type="text" id="simple_tracking_server_url" name="simple_tracking_server_url" value="' . esc_attr($value) . '" class="regular-text">';
echo '<p class="description">Enter the tracking server URL without https:// (e.g., tracking1.karlbreuer.com)</p>'; echo '<p class="description">Enter the tracking server URL without https:// (e.g., tracking1.karlbreuer.com)</p>';
echo '<p class="description">You will find this in your domain screen in the Palantics app</p>'; echo '<p class="description">You will find this in your domain screen in the Palantics app</p>';
}
/**
* Track classes callback
*/
public function track_classes_callback() {
$value = get_option('simple_tracking_track_classes', '');
echo '<input type="text" id="simple_tracking_track_classes" name="simple_tracking_track_classes" value="' . esc_attr($value) . '" class="regular-text">';
echo '<p class="description">Enter comma-separated class names to automatically track clicks on elements with these classes (e.g., cta-button, featured-product)</p>';
} }
/** /**
@ -322,6 +504,29 @@ document.addEventListener("DOMContentLoaded", function() {
submit_button(); submit_button();
?> ?>
</form> </form>
<div style="background-color: #fff; padding: 20px; margin-top: 20px; border: 1px solid #ccc; border-radius: 4px;">
<h2>Manual Tracking Methods</h2>
<div style="margin-bottom: 20px;">
<h3>Method 1: Using Data Attributes</h3>
<p>Add the <code>data-track</code> attribute to any HTML element to track clicks:</p>
<pre style="background-color: #f5f5f5; padding: 10px; border-radius: 4px;">&lt;button data-track="signup_button_click"&gt;Sign Up&lt;/button&gt;</pre>
</div>
<div style="margin-bottom: 20px;">
<h3>Method 2: Using Shortcode</h3>
<p>Wrap any content with the shortcode to track clicks:</p>
<pre style="background-color: #f5f5f5; padding: 10px; border-radius: 4px;">[track_element event="download_click" class="your-class" style="your-style"]
Your content here (can include other shortcodes)
[/track_element]</pre>
</div>
<div>
<h3>Method 3: Using Direct JavaScript</h3>
<p>You can also manually add <code>onclick="tE('your_event_name')"</code> to any HTML element.</p>
</div>
</div>
</div> </div>
<?php <?php
} }
@ -336,10 +541,10 @@ document.addEventListener("DOMContentLoaded", function() {
} }
// Initialize the plugin // Initialize the plugin
function simple_tracking_init() { function simplified_tracking_init() {
Simple_Tracking_Plugin::get_instance(); Simplified_Tracking_Plugin::get_instance();
} }
add_action('plugins_loaded', 'simple_tracking_init'); add_action('plugins_loaded', 'simplified_tracking_init');
// Register activation hook // Register activation hook
register_activation_hook(__FILE__, array('Simple_Tracking_Plugin', 'activate')); register_activation_hook(__FILE__, array('Simplified_Tracking_Plugin', 'activate'));

View File

@ -0,0 +1,21 @@
/**
* Tracking Block Styles
*/
.tracking-block-wrapper {
border: 1px dashed #007cba;
padding: 10px;
position: relative;
}
.tracking-block-notice {
background: #007cba;
color: white;
padding: 5px 10px;
font-size: 12px;
position: absolute;
top: 0;
right: 0;
border-bottom-left-radius: 4px;
display: flex;
align-items: center;
}