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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.php eol=lf
14 changes: 5 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ docker compose --profile test run --rm test
# Build plugin zip
docker compose --profile build run --rm build

# Run WordPress.org Plugin Check
docker compose up -d && docker compose --profile plugin-check run --rm plugin-check
# Run WordPress.org Plugin Check (package first, then check)
./package.sh && docker compose --profile plugin-check run --rm plugin-check

# Clean up everything (including volumes)
docker compose down -v
Expand Down Expand Up @@ -86,15 +86,11 @@ docker compose --profile test run --rm test vendor/bin/phpunit --verbose

## Plugin Check (WordPress.org Validation)

Run the official [WordPress Plugin Check](https://wordpress.org/plugins/plugin-check/) tool to validate the plugin against WordPress.org submission requirements and best practices.
Run the official [WordPress Plugin Check](https://wordpress.org/plugins/plugin-check/) tool to validate the plugin against WordPress.org submission requirements and best practices. The check runs against the packaged zip to match exactly what WordPress.org reviewers see.

```bash
# Run all checks (comprehensive - for development)
docker compose up -d && docker compose --profile plugin-check run --rm plugin-check

# Run only plugin_repo category (required checks for WordPress.org submission)
docker compose up -d && docker compose --profile plugin-check run --rm plugin-check \
wp plugin check betterlytics --categories=plugin_repo --format=table
# Package the plugin and run all checks
./package.sh && docker compose --profile plugin-check run --rm plugin-check
```

### Check Categories
Expand Down
9 changes: 5 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ services:
volumes:
- .:/app
working_dir: /app
command: sh -c "composer install && vendor/bin/phpcs"
command: sh -c "git config --global --add safe.directory /app && composer install && vendor/bin/phpcs -v"
profiles:
- lint

Expand All @@ -98,7 +98,7 @@ services:
volumes:
- .:/app
working_dir: /app
command: sh -c "composer install && vendor/bin/phpcbf"
command: sh -c "git config --global --add safe.directory /app && composer install && vendor/bin/phpcbf"
profiles:
- lint-fix

Expand Down Expand Up @@ -161,7 +161,7 @@ services:
WORDPRESS_DB_NAME: ${MYSQL_DATABASE:-wordpress}
volumes:
- wordpress_data:/var/www/html
- .:/var/www/html/wp-content/plugins/betterlytics
- ./betterlytics.zip:/tmp/betterlytics.zip:ro
depends_on:
wordpress:
condition: service_healthy
Expand All @@ -173,7 +173,8 @@ services:
- plugin-check
command: >
sh -c '
echo "Installing Plugin Check..." &&
echo "Installing plugin from betterlytics.zip..." &&
wp plugin install /tmp/betterlytics.zip --force --activate &&
wp plugin install plugin-check --activate &&
echo "" &&
echo "Running Plugin Check on betterlytics..." &&
Expand Down
41 changes: 12 additions & 29 deletions public/class-betterlytics-public.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,6 @@ public function __construct( $plugin_name, $version ) {
public function inject_tracking_script() {
$options = Betterlytics_Options::get_options();

// Debug: Log tracking check.
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$tracking_status = Betterlytics_Options::is_tracking_enabled() ? 'ENABLED' : 'DISABLED';
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug only.
error_log( '[Betterlytics] Tracking status: ' . $tracking_status );
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug only.
error_log( '[Betterlytics] Options: ' . wp_json_encode( $options ) );
}

if ( ! Betterlytics_Options::is_tracking_enabled() ) {
return;
}
Expand All @@ -83,8 +74,8 @@ public function inject_tracking_script() {
]
);

// Add filter for data-* attributes.
add_filter( 'script_loader_tag', [ $this, 'add_tracker_script_attributes' ], 10, 2 );
// Add data-* attributes via wp_script_attributes filter.
add_filter( 'wp_script_attributes', [ $this, 'add_tracker_script_attributes' ] );

// Build inline script for event queue buffer.
$inline_script = 'window.betterlytics = window.betterlytics || { event: function() { (window.betterlytics.q = window.betterlytics.q || []).push(arguments); } };';
Expand All @@ -107,30 +98,22 @@ public function inject_tracking_script() {
* Add data attributes to the tracking script tag.
*
* @since 1.0.0
* @param string $tag The script tag HTML.
* @param string $handle The script handle.
* @return string Modified script tag.
* @param array $attr Script tag attributes.
* @return array Modified attributes.
*/
public function add_tracker_script_attributes( $tag, $handle ) {
if ( 'betterlytics-tracker' !== $handle ) {
return $tag;
public function add_tracker_script_attributes( $attr ) {
if ( ! isset( $attr['id'] ) || 'betterlytics-tracker-js' !== $attr['id'] ) {
return $attr;
}

$options = Betterlytics_Options::get_options();

// Build data attributes string.
$data_attrs = sprintf(
' data-site-id="%s" data-server-url="%s" data-outbound-links="%s" data-web-vitals="%s"',
esc_attr( $options['site_id'] ),
esc_url( $options['server_url'] ),
esc_attr( $options['track_outbound']['mode'] ),
! empty( $options['track_web_vitals'] ) ? 'true' : 'false'
);

// Insert data attributes before the closing >.
$tag = str_replace( '></script>', $data_attrs . '></script>', $tag );
$attr['data-site-id'] = esc_attr( $options['site_id'] );
$attr['data-server-url'] = esc_url( $options['server_url'] );
$attr['data-outbound-links'] = esc_attr( $options['track_outbound']['mode'] );
$attr['data-web-vitals'] = ! empty( $options['track_web_vitals'] ) ? 'true' : 'false';

return $tag;
return $attr;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/class-betterlytics-test-case.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Base test case class.
*/
class Betterlytics_Test_Case extends WP_UnitTestCase {
abstract class Betterlytics_Test_Case extends WP_UnitTestCase {

/**
* Set up test fixtures.
Expand Down
72 changes: 38 additions & 34 deletions tests/test-public.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,13 @@ public function test_web_vitals_enabled() {
)
);

$this->public->inject_tracking_script();

// Check the data attributes via the filter method.
$test_tag = '<script src="test.js"></script>';
$result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
$attr = array(
'id' => 'betterlytics-tracker-js',
'src' => 'https://analytics.example.com/script.js',
);
$result = $this->public->add_tracker_script_attributes( $attr );

$this->assertStringContainsString( 'data-web-vitals="true"', $result );
$this->assertEquals( 'true', $result['data-web-vitals'] );
}

/**
Expand All @@ -246,13 +246,13 @@ public function test_web_vitals_disabled() {
)
);

$this->public->inject_tracking_script();

// Check the data attributes via the filter method.
$test_tag = '<script src="test.js"></script>';
$result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
$attr = array(
'id' => 'betterlytics-tracker-js',
'src' => 'https://analytics.example.com/script.js',
);
$result = $this->public->add_tracker_script_attributes( $attr );

$this->assertStringContainsString( 'data-web-vitals="false"', $result );
$this->assertEquals( 'false', $result['data-web-vitals'] );
}

/**
Expand All @@ -267,13 +267,13 @@ public function test_outbound_links_domain_mode() {
)
);

$this->public->inject_tracking_script();

// Check the data attributes via the filter method.
$test_tag = '<script src="test.js"></script>';
$result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
$attr = array(
'id' => 'betterlytics-tracker-js',
'src' => 'https://analytics.example.com/script.js',
);
$result = $this->public->add_tracker_script_attributes( $attr );

$this->assertStringContainsString( 'data-outbound-links="domain"', $result );
$this->assertEquals( 'domain', $result['data-outbound-links'] );
}

/**
Expand All @@ -288,13 +288,13 @@ public function test_outbound_links_full_mode() {
)
);

$this->public->inject_tracking_script();

// Check the data attributes via the filter method.
$test_tag = '<script src="test.js"></script>';
$result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
$attr = array(
'id' => 'betterlytics-tracker-js',
'src' => 'https://analytics.example.com/script.js',
);
$result = $this->public->add_tracker_script_attributes( $attr );

$this->assertStringContainsString( 'data-outbound-links="full"', $result );
$this->assertEquals( 'full', $result['data-outbound-links'] );
}

/**
Expand All @@ -309,13 +309,13 @@ public function test_outbound_links_off_mode() {
)
);

$this->public->inject_tracking_script();

// Check the data attributes via the filter method.
$test_tag = '<script src="test.js"></script>';
$result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
$attr = array(
'id' => 'betterlytics-tracker-js',
'src' => 'https://analytics.example.com/script.js',
);
$result = $this->public->add_tracker_script_attributes( $attr );

$this->assertStringContainsString( 'data-outbound-links="off"', $result );
$this->assertEquals( 'off', $result['data-outbound-links'] );
}

/**
Expand All @@ -329,10 +329,14 @@ public function test_filter_ignores_other_handles() {
)
);

$test_tag = '<script src="other.js"></script>';
$result = $this->public->add_tracker_script_attributes( $test_tag, 'other-script' );
$attr = array(
'id' => 'other-script-js',
'src' => 'https://example.com/other.js',
);
$result = $this->public->add_tracker_script_attributes( $attr );

// Should return unchanged.
$this->assertEquals( $test_tag, $result );
// Should return unchanged — no data-* keys added.
$this->assertArrayNotHasKey( 'data-site-id', $result );
$this->assertEquals( $attr, $result );
}
}