Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .wordpress-org/banner-772x250.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .wordpress-org/icon-128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 8 additions & 11 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The Betterlytics plugin stores all settings in a single WordPress option (`bette
"track_404": { "enabled": false },
"track_search": { "enabled": false },
"track_downloads": { "enabled": false },
"track_css_events": { "enabled": false }
"track_custom_html_attribute": { "enabled": false }
}
```

Expand All @@ -27,7 +27,7 @@ Configure the plugin directly from your deployment scripts:

```bash
# Set all options at once (JSON)
wp option update betterlytics_options '{"site_id":"abc123","server_url":"https://analytics.example.com/track","script_url":"https://analytics.example.com/analytics.js","enabled":true}' --format=json
wp option update betterlytics_options '{"site_id":"abc123","server_url":"https://analytics.example.com/event","script_url":"https://analytics.example.com/analytics.js","enabled":true}' --format=json

# Or pipe from a config file
wp option update betterlytics_options --format=json < betterlytics-config.json
Expand Down Expand Up @@ -61,12 +61,10 @@ add_action( 'init', function() {
}

update_option( 'betterlytics_options', [
'site_id' => $site_id,
'server_url' => getenv( 'BETTERLYTICS_SERVER_URL' ) ?: 'https://betterlytics.io/event',
'script_url' => getenv( 'BETTERLYTICS_SCRIPT_URL' ) ?: 'https://betterlytics.io/analytics.js',
'enabled' => filter_var( getenv( 'BETTERLYTICS_ENABLED' ) ?: 'true', FILTER_VALIDATE_BOOLEAN ),
'track_logged_in' => filter_var( getenv( 'BETTERLYTICS_TRACK_LOGGED_IN' ) ?: 'false', FILTER_VALIDATE_BOOLEAN ),
'hooks' => [],
'site_id' => $site_id,
'server_url' => getenv( 'BETTERLYTICS_SERVER_URL' ) ?: 'https://betterlytics.io/event',
'script_url' => getenv( 'BETTERLYTICS_SCRIPT_URL' ) ?: 'https://betterlytics.io/analytics.js',
'enabled' => filter_var( getenv( 'BETTERLYTICS_ENABLED' ) ?: 'true', FILTER_VALIDATE_BOOLEAN ),
]);

update_option( 'betterlytics_configured_by_env', true );
Expand All @@ -81,10 +79,9 @@ services:
wordpress:
environment:
BETTERLYTICS_SITE_ID: "your-site-id"
BETTERLYTICS_SERVER_URL: "https://analytics.example.com/track"
BETTERLYTICS_SERVER_URL: "https://analytics.example.com/event"
BETTERLYTICS_SCRIPT_URL: "https://analytics.example.com/analytics.js"
BETTERLYTICS_ENABLED: "true"
BETTERLYTICS_TRACK_LOGGED_IN: "false"
```

## Config File Approach
Expand All @@ -94,7 +91,7 @@ Keep a `betterlytics-config.json` in your deployment repo for reproducible confi
```json
{
"site_id": "production-site-id",
"server_url": "https://analytics.example.com/track",
"server_url": "https://analytics.example.com/event",
"script_url": "https://analytics.example.com/analytics.js",
"enabled": true
}
Expand Down
1 change: 0 additions & 1 deletion Dockerfile.test
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ RUN apt-get update && apt-get install -y \
unzip \
libzip-dev \
default-mysql-client \
subversion \
&& docker-php-ext-install mysqli pdo pdo_mysql zip \
&& rm -rf /var/lib/apt/lists/*

Expand Down
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,18 @@ Official WordPress plugin for [Betterlytics](https://betterlytics.io) - privacy-

### General Settings

| Setting | Description |
| ------------------------- | ---------------------------------------------------------------------- |
| **Enable Tracking** | Toggle tracking on/off |
| **Site ID** | Your unique Site ID from the Betterlytics dashboard |
| **Server URL** | Tracking endpoint (default: `https://betterlytics.io/event`) |
| **Script URL** | Analytics script URL (default: `https://betterlytics.io/analytics.js`) |
| **Track Logged-in Users** | Include/exclude logged-in users from analytics |
| Setting | Description |
| ------------------- | ---------------------------------------------------------------------- |
| **Enable Tracking** | Toggle tracking on/off |
| **Site ID** | Your unique Site ID from the Betterlytics dashboard |
| **Server URL** | Tracking endpoint (default: `https://betterlytics.io/event`) |
| **Script URL** | Analytics script URL (default: `https://betterlytics.io/analytics.js`) |

### Self-Hosting

If you're self-hosting Betterlytics, update the Server URL and Script URL to point to your instance:

- **Server URL**: `https://your-instance.com/track`
- **Server URL**: `https://your-instance.com/event`
- **Script URL**: `https://your-instance.com/analytics.js`

### Automated Configuration (CI/CD)
Expand Down Expand Up @@ -104,15 +103,15 @@ if ( Betterlytics_Options::is_tracking_enabled() ) {

```php
$options = Betterlytics_Options::get_options();
// Returns: site_id, server_url, script_url, enabled, track_logged_in, hooks
// Returns: site_id, server_url, script_url, enabled, track_outbound, etc.

// Get a single option
$site_id = Betterlytics_Options::get( 'site_id' );
```

## Requirements

- WordPress 6.0+
- WordPress 5.0+
- PHP 7.4+
- pnpm 9.0+ (for developers)

Expand Down
19 changes: 11 additions & 8 deletions admin/class-betterlytics-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,22 +97,25 @@ public function sanitize_options( $input ) {
$page = isset( $_POST['option_page'] ) ? sanitize_text_field( wp_unslash( $_POST['option_page'] ) ) : '';

if ( 'betterlytics_settings' === $page ) {
$options['enabled'] = ! empty( $input['enabled'] );
$options['site_id'] = sanitize_text_field( $input['site_id'] ?? '' );
$options['server_url'] = esc_url_raw( $input['server_url'] ?? 'https://betterlytics.io/event' );
$options['enabled'] = ! empty( $input['enabled'] );
$options['site_id'] = sanitize_text_field( $input['site_id'] ?? '' );

// Only update URLs if explicitly provided.
if ( ! empty( $input['server_url'] ) ) {
$options['server_url'] = esc_url_raw( $input['server_url'] );
}

// Allow script_url to be updated programmatically (e.g. config.json) even if hidden in UI.
if ( ! empty( $input['script_url'] ) ) {
$options['script_url'] = esc_url_raw( $input['script_url'] );
}

$options['track_web_vitals'] = ! empty( $input['track_web_vitals'] );

$checkbox_keys = [
'track_404' => [ 'enabled' ],
'track_search' => [ 'enabled', 'include_query' ],
'track_downloads' => [ 'enabled' ],
'track_css_events' => [ 'enabled' ],
'track_404' => [ 'enabled' ],
'track_search' => [ 'enabled', 'include_query' ],
'track_downloads' => [ 'enabled' ],
'track_custom_html_attribute' => [ 'enabled' ],
];

foreach ( $checkbox_keys as $key => $subkeys ) {
Expand Down
12 changes: 6 additions & 6 deletions admin/components/views/settings/betterlytics-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,13 @@
Betterlytics_Admin_Controller::render_component(
'ui/setting-row',
[
'label' => __( 'CSS Class Events', 'betterlytics' ),
'name' => 'betterlytics_options[track_css_events][enabled]',
'checked' => ! empty( $betterlytics_options['track_css_events']['enabled'] ),
'label' => __( 'Custom HTML Attribute Events', 'betterlytics' ),
'name' => 'betterlytics_options[track_custom_html_attribute][enabled]',
'checked' => ! empty( $betterlytics_options['track_custom_html_attribute']['enabled'] ),
'description' => sprintf(
/* translators: %s: CSS class example */
__( 'Track clicks on elements with %s class', 'betterlytics' ),
'<code class="bg-muted px-1.5 py-0.5 rounded text-primary">betterlytics-event-name=YourEvent</code>'
/* translators: %s: HTML attribute example */
__( 'Track clicks on elements with %s attribute', 'betterlytics' ),
'<code class="bg-muted px-1.5 py-0.5 rounded text-primary">data-betterlytics-event="some-event-name"</code>'
),
'help_path' => 'integration/custom-events',
]
Expand Down
13 changes: 5 additions & 8 deletions betterlytics.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
*
* @package Betterlytics
* @author Betterlytics
* @copyright 2024 Betterlytics
* @copyright 2026 Betterlytics
* @license GPL-2.0-or-later
*
* @wordpress-plugin
* Plugin Name: Betterlytics
* Plugin URI: https://github.com/betterlytics/betterlytics-wordpress
* Description: Privacy-first analytics for WordPress. Automatically adds the Betterlytics tracking script and provides easy WordPress action hooks integration.
* Version: 1.0.0
* Requires at least: 6.0
* Requires at least: 5.0
* Requires PHP: 7.4
* Author: Betterlytics
* Author URI: https://betterlytics.io
Expand Down Expand Up @@ -67,12 +67,9 @@ function betterlytics_plugin_action_links( $links ) {
$settings_link = '<a href="' . admin_url( 'options-general.php?page=betterlytics&tab=settings' ) . '">' . __( 'Settings', 'betterlytics' ) . '</a>';
array_unshift( $links, $settings_link );

// Add dashboard link if site_id is configured.
$options = get_option( 'betterlytics_options', [] );
if ( ! empty( $options['site_id'] ) ) {
$dashboard_link = '<a href="https://betterlytics.io/dashboards/' . esc_attr( $options['site_id'] ) . '" target="_blank">' . __( 'Dashboard', 'betterlytics' ) . '</a>';
array_unshift( $links, $dashboard_link );
}
// Add dashboard link.
$dashboard_link = '<a href="https://betterlytics.io/dashboards" target="_blank">' . __( 'Dashboard', 'betterlytics' ) . '</a>';
array_unshift( $links, $dashboard_link );

return $links;
}
Expand Down
20 changes: 9 additions & 11 deletions bin/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,18 @@ if [ ! -f "$WP_TESTS_DIR/includes/functions.php" ]; then
curl --progress-bar https://wordpress.org/latest.tar.gz | tar xz -C "$WP_CORE_DIR" --strip-components=1
echo " Done!"

# Download test suite
echo "[2/4] Downloading test suite includes..."
svn export --force --ignore-externals https://develop.svn.wordpress.org/tags/6.7/tests/phpunit/includes/ "$WP_TESTS_DIR/includes"
# Download test suite from GitHub mirror (more reliable than SVN)
echo "[2/4] Downloading test suite from GitHub..."
WP_DEVELOP_DIR=$(mktemp -d)
git clone --depth=1 --branch=6.7 https://github.com/WordPress/wordpress-develop.git "$WP_DEVELOP_DIR"
cp -r "$WP_DEVELOP_DIR/tests/phpunit/includes" "$WP_TESTS_DIR/includes"
cp -r "$WP_DEVELOP_DIR/tests/phpunit/data" "$WP_TESTS_DIR/data"
cp "$WP_DEVELOP_DIR/wp-tests-config-sample.php" "$WP_TESTS_DIR/wp-tests-config.php"
rm -rf "$WP_DEVELOP_DIR"
echo " Done!"

echo "[3/4] Downloading test suite data..."
svn export --force --ignore-externals https://develop.svn.wordpress.org/tags/6.7/tests/phpunit/data/ "$WP_TESTS_DIR/data"
echo " Done!"

# Download wp-tests-config.php
echo "[4/4] Configuring test environment..."
curl -s https://develop.svn.wordpress.org/tags/6.7/wp-tests-config-sample.php > "$WP_TESTS_DIR/wp-tests-config.php"

# Configure wp-tests-config.php
echo "[3/4] Configuring test environment..."
sed -i "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR/wp-tests-config.php"
sed -i "s:__DIR__ . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR/wp-tests-config.php"
sed -i "s/youremptytestdbnamehere/$WORDPRESS_DB_NAME/" "$WP_TESTS_DIR/wp-tests-config.php"
Expand Down
6 changes: 3 additions & 3 deletions demo/config.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"site_id": "betterlytics-wp-mklt1198",
"site_id": "",
"server_url": "http://localhost:3001/event",
"script_url": "http://localhost:3006/analytics.js",
"enabled": true,
"enabled": false,
"track_web_vitals": false,

"track_404": { "enabled": true },
"track_search": { "enabled": true },
"track_outbound": { "mode": "domain" },
"track_downloads": { "enabled": true },
"track_css_events": { "enabled": true }
"track_custom_html_attribute": { "enabled": true }
}
11 changes: 11 additions & 0 deletions demo/mu-plugins/betterlytics-demo.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ function betterlytics_demo_render_test_page( $content ) {
</p>
</div>

<h2>HTML Attribute Testing</h2>
<div class="test-section">
<p>Click these buttons to fire custom HTML attributed Betterlytics events:</p>
<button data-betterlytics-event="YourEvent">
Fire: YourEvent
</button>
<button class="secondary" data-betterlytics-event="test-page-action">
Fire: test-page-action
</button>
</div>

<h2>WordPress Hook Testing</h2>
<?php if ( comments_open() ) : ?>
<p style="margin-top: 15px;"><strong>Post a comment</strong> to trigger the <code>comment_post</code> hook:</p>
Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ services:
volumes:
- wordpress_data:/var/www/html
- .:/var/www/html/wp-content/plugins/betterlytics
- ./demo/mu-plugins:/var/www/html/wp-content/mu-plugins
depends_on:
db:
condition: service_healthy
Expand Down Expand Up @@ -214,6 +215,11 @@ services:
sh -c '
echo "Setting up demo environment..." &&

# Enable pretty permalinks
echo "Enabling pretty permalinks..." &&
wp rewrite structure "/%postname%/" --hard &&
wp rewrite flush --hard &&

# Create a demo page for testing custom events
if ! wp post list --post_type=page --name=betterlytics-test --format=ids | grep -q .; then
echo "Creating test page..." &&
Expand Down
22 changes: 11 additions & 11 deletions includes/class-betterlytics-options.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,29 @@ class Betterlytics_Options {
* @var array
*/
const DEFAULTS = [
'site_id' => '',
'server_url' => 'https://betterlytics.io/event',
'script_url' => 'https://betterlytics.io/analytics.js',
'enabled' => false,
'track_web_vitals' => false,
'track_404' => [
'site_id' => '',
'server_url' => 'https://betterlytics.io/event',
'script_url' => 'https://betterlytics.io/analytics.js',
'enabled' => false,
'track_web_vitals' => false,
'track_404' => [
'enabled' => false,
'metadata' => [],
],
'track_search' => [
'track_search' => [
'enabled' => false,
'include_query' => false,
'metadata' => [],
],
'track_outbound' => [
'track_outbound' => [
'mode' => 'domain',
'metadata' => [],
],
'track_downloads' => [
'track_downloads' => [
'enabled' => false,
'metadata' => [],
],
'track_css_events' => [
'track_custom_html_attribute' => [
'enabled' => false,
'metadata' => [],
],
Expand All @@ -68,7 +68,7 @@ public static function get_options() {
'track_404',
'track_search',
'track_downloads',
'track_css_events',
'track_custom_html_attribute',
];

foreach ( $event_keys as $key ) {
Expand Down
20 changes: 10 additions & 10 deletions public/class-betterlytics-public.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public function enqueue_event_scripts() {
}

$options = Betterlytics_Options::get_options();
$needs_js = ! empty( $options['track_downloads']['enabled'] ) || ! empty( $options['track_css_events']['enabled'] );
$needs_js = ! empty( $options['track_downloads']['enabled'] ) || ! empty( $options['track_custom_html_attribute']['enabled'] );

if ( ! $needs_js ) {
return;
Expand All @@ -120,14 +120,14 @@ public function enqueue_event_scripts() {
true
);

wp_localize_script(
'betterlytics-events',
'betterlyticsEvents',
[
'trackDownloads' => ! empty( $options['track_downloads'] ),
'trackCssEvents' => ! empty( $options['track_css_events'] ),
]
);
wp_localize_script(
'betterlytics-events',
'betterlyticsEvents',
[
'trackDownloads' => ! empty( $options['track_downloads']['enabled'] ),
'trackCustomHtmlAttr' => ! empty( $options['track_custom_html_attribute']['enabled'] ),
]
);
}

/**
Expand All @@ -145,7 +145,7 @@ public function output_queued_events() {
echo "<script>\n";
foreach ( $betterlytics_queued_events as $event ) {
$name = esc_js( $event['name'] );
$props = wp_json_encode( $event['properties'], JSON_HEX_TAG | JSON_HEX_AMP );
$props = wp_json_encode( $event['properties'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_FORCE_OBJECT );
echo "betterlytics.event('" . esc_js( $name ) . "', " . $props . ");\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo "</script>\n";
Expand Down
Loading