Skip to content

Commit

Permalink
Merge pull request #214 from plausible/woocommerce_integration
Browse files Browse the repository at this point in the history
Added: Woocommerce integration when Ecommerce Revenue tracking is enabled.
  • Loading branch information
Dan0sz authored Jun 7, 2024
2 parents ae32219 + 98f360f commit 94e324b
Show file tree
Hide file tree
Showing 14 changed files with 912 additions and 171 deletions.
28 changes: 28 additions & 0 deletions assets/src/js/compatibility/woocommerce.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Plausible Analytics
*
* WooCommerce compatibility JS.
*/
const {fetch: originalFetch} = window;

window.fetch = (...args) => {
let [resource, config] = args;

if (config.body === undefined) {
return originalFetch(resource, config);
}

let data = JSON.parse(config.body);

data.requests.forEach(function (request) {
if (!request.path.includes('cart/add-item')) {
return;
}

request.body._wp_http_referer = window.location.href;
});

config.body = JSON.stringify(data);

return originalFetch(resource, config);
};
29 changes: 4 additions & 25 deletions src/Admin/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Exception;
use Plausible\Analytics\WP\Helpers;
use Plausible\Analytics\WP\Proxy;

class Module {
/**
Expand Down Expand Up @@ -252,31 +253,9 @@ private function test_proxy( $run = true ) {
return false; // @codeCoverageIgnore
}

$namespace = Helpers::get_proxy_resource( 'namespace' );
$base = Helpers::get_proxy_resource( 'base' );
$endpoint = Helpers::get_proxy_resource( 'endpoint' );
$request = new \WP_REST_Request( 'POST', "/$namespace/v1/$base/$endpoint" );
$request->set_body(
wp_json_encode(
[
'd' => 'plausible.test',
'n' => 'pageview',
'u' => 'https://plausible.test/test',
]
)
);

/** @var \WP_REST_Response $result */
try {
$result = rest_do_request( $request );
} catch ( \Exception $e ) { // @codeCoverageIgnore
/**
* There's no need to handle the error, because we don't want to display it anyway.
* We'll leave the parameter for backwards compatibility.
*/
return false; // @codeCoverageIgnore
}
$proxy = new Proxy( false );
$result = $proxy->do_request( 'pageview', 'plausible.test', 'https://plausible.test/test' );

return wp_remote_retrieve_response_code( $result->get_data() ) === 202;
return wp_remote_retrieve_response_code( $result ) === 202;
}
}
113 changes: 94 additions & 19 deletions src/Admin/Provisioning.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

use Plausible\Analytics\WP\Client;
use Plausible\Analytics\WP\Client\ApiException;
use Plausible\Analytics\WP\Client\Model\GoalCreateRequestCustomEvent;
use Plausible\Analytics\WP\Helpers;
use Plausible\Analytics\WP\Integrations;
use Plausible\Analytics\WP\Integrations\WooCommerce;

class Provisioning {
/**
Expand All @@ -21,11 +25,7 @@ class Provisioning {
/**
* @var string[] $custom_event_goals
*/
private $custom_event_goals = [
'404' => '404',
'outbound-links' => 'Outbound Link: Click',
'file-downloads' => 'File Download',
];
private $custom_event_goals = [];

/**
* @var string[] $custom_pageview_properties
Expand Down Expand Up @@ -59,6 +59,12 @@ public function __construct( $client = null ) {
$this->client = new Client();
}

$this->custom_event_goals = [
'404' => __( '404', 'plausible-analytics' ),
'outbound-links' => __( 'Outbound Link: Click', 'plausible-analytics' ),
'file-downloads' => __( 'File Download', 'plausible-analytics' ),
];

$this->init();
}

Expand All @@ -76,7 +82,8 @@ private function init() {
}

add_action( 'update_option_plausible_analytics_settings', [ $this, 'create_shared_link' ], 10, 2 );
add_action( 'update_option_plausible_analytics_settings', [ $this, 'create_goals' ], 10, 2 );
add_action( 'update_option_plausible_analytics_settings', [ $this, 'maybe_create_goals' ], 10, 2 );
add_action( 'update_option_plausible_analytics_settings', [ $this, 'maybe_create_woocommerce_goals' ], 10, 2 );
add_action( 'update_option_plausible_analytics_settings', [ $this, 'maybe_delete_goals' ], 11, 2 );
add_action( 'update_option_plausible_analytics_settings', [ $this, 'maybe_create_custom_properties' ], 11, 2 );
}
Expand Down Expand Up @@ -117,36 +124,62 @@ public function create_shared_link( $old_settings, $settings ) {
* @param $old_settings
* @param $settings
*/
public function create_goals( $old_settings, $settings ) {
public function maybe_create_goals( $old_settings, $settings ) {
$enhanced_measurements = array_filter( $settings[ 'enhanced_measurements' ] );

if ( empty( $enhanced_measurements ) ) {
return; // @codeCoverageIgnore
}

$custom_event_keys = array_keys( $this->custom_event_goals );
$create_request = new Client\Model\GoalCreateRequestBulkGetOrCreate();
$goals = [];

foreach ( $enhanced_measurements as $measurement ) {
if ( ! in_array( $measurement, $custom_event_keys ) ) {
continue; // @codeCoverageIgnore
}

$goals[] = new Client\Model\GoalCreateRequestCustomEvent(
[
'goal' => [
'event_name' => $this->custom_event_goals[ $measurement ],
],
'goal_type' => 'Goal.CustomEvent',
]
);
$goals[] = $this->create_request_custom_event( $this->custom_event_goals[ $measurement ] );
}

$this->create_goals( $goals );
}

/**
* @param string $name Event Name
* @param string $type CustomEvent|Revenue|Pageview
* @param string $currency Required if $type is Revenue
*
* @return GoalCreateRequestCustomEvent
*/
private function create_request_custom_event( $name, $type = 'CustomEvent', $currency = '' ) {
$props = [
'goal' => [
'event_name' => $name,
],
'goal_type' => "Goal.$type",
];

if ( $type === 'Revenue' ) {
$props[ 'goal' ][ 'currency' ] = $currency;
}

return new Client\Model\GoalCreateRequestCustomEvent( $props );
}

/**
* Create the goals using the API client and updates the IDs in the database.
*
* @param $goals
*
* @return void
*/
private function create_goals( $goals ) {
if ( empty( $goals ) ) {
return; // @codeCoverageIgnore
}

$create_request = new Client\Model\GoalCreateRequestBulkGetOrCreate();
$create_request->setGoals( $goals );
$response = $this->client->create_goals( $create_request );

Expand All @@ -165,6 +198,33 @@ public function create_goals( $old_settings, $settings ) {
}
}

/**
* @param $old_settings
* @param $settings
*
* @return void
*/
public function maybe_create_woocommerce_goals( $old_settings, $settings ) {
if ( ! Helpers::is_enhanced_measurement_enabled( 'revenue', $settings[ 'enhanced_measurements' ] ) || ! Integrations::is_wc_active() ) {
return; // @codeCoverageIgnore
}

$goals = [];
$woocommerce = new WooCommerce( false );

foreach ( $woocommerce->event_goals as $event_key => $event_goal ) {
if ( $event_key === 'purchase' ) {
$goals[] = $this->create_request_custom_event( $event_goal, 'Revenue', get_woocommerce_currency() );

continue;
}

$goals[] = $this->create_request_custom_event( $event_goal );
}

$this->create_goals( $goals );
}

/**
* Delete Custom Event Goals when an Enhanced Measurement is disabled.
*
Expand Down Expand Up @@ -206,15 +266,30 @@ public function maybe_delete_goals( $old_settings, $settings ) {
public function maybe_create_custom_properties( $old_settings, $settings ) {
$enhanced_measurements = $settings[ 'enhanced_measurements' ];

if ( ! in_array( 'pageview-props', $enhanced_measurements ) ) {
if ( ! Helpers::is_enhanced_measurement_enabled( 'pageview-props', $enhanced_measurements ) &&
! Helpers::is_enhanced_measurement_enabled( 'revenue', $enhanced_measurements ) ) {
return; // @codeCoverageIgnore
}

$create_request = new Client\Model\CustomPropEnableRequestBulkEnable();
$properties = [];

foreach ( $this->custom_pageview_properties as $property ) {
$properties[] = new Client\Model\CustomProp( [ 'custom_prop' => [ 'key' => $property ] ] );
/**
* Enable Custom Properties for Authors & Categories option.
*/
if ( Helpers::is_enhanced_measurement_enabled( 'pageview-props', $enhanced_measurements ) ) {
foreach ( $this->custom_pageview_properties as $property ) {
$properties[] = new Client\Model\CustomProp( [ 'custom_prop' => [ 'key' => $property ] ] );
}
}

/**
* Create Custom Properties for WooCommerce integration.
*/
if ( Helpers::is_enhanced_measurement_enabled( 'revenue', $enhanced_measurements ) && Integrations::is_wc_active() ) {
foreach ( WooCommerce::CUSTOM_PROPERTIES as $property ) {
$properties[] = new Client\Model\CustomProp( [ 'custom_prop' => [ 'key' => $property ] ] );
}
}

$create_request->setCustomProps( $properties );
Expand Down
12 changes: 9 additions & 3 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,12 @@ public function validate_api_token() {
$token = $this->api_instance->getConfig()->getPassword();
$is_valid = strpos( $token, 'plausible-plugin' ) !== false && ! empty( $features->getGoals() ) && $data_domain === Helpers::get_domain();

set_transient( 'plausible_analytics_valid_token', [ $token => $is_valid ], 86400 );
/**
* Don't cache invalid API tokens.
*/
if ( $is_valid ) {
set_transient( 'plausible_analytics_valid_token', [ $token => true ], 86400 ); // @codeCoverageIgnore
}

return $is_valid;
}
Expand All @@ -71,9 +76,10 @@ public function validate_api_token() {
* @return bool
*/
public function is_api_token_valid() {
$token = $this->api_instance->getConfig()->getPassword();
$token = $this->api_instance->getConfig()->getPassword();
$valid_tokens = get_transient( 'plausible_analytics_valid_token' );

return ! empty( get_transient( 'plausible_analytics_valid_token' )[ $token ] );
return isset( $valid_tokens[ $token ] ) && $valid_tokens[ $token ] === true;
}

/**
Expand Down
36 changes: 20 additions & 16 deletions src/Compatibility.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Plausible Analytics | Filters.
* Plausible Analytics | Compatibility.
*
* @since 1.2.5
* @package WordPress
Expand All @@ -11,6 +11,9 @@

use Exception;

/**
* @codeCoverageIgnore Because this is to be tested in a headless browser.
*/
class Compatibility {
/**
* A list of filters and actions to prevent our script from being manipulated by other plugins, known to cause issues.
Expand All @@ -24,12 +27,11 @@ public function __construct() {
add_filter( 'autoptimize_filter_js_exclude', [ $this, 'exclude_plausible_js_as_string' ] );
}

// WP Rocket
if ( defined( 'WP_ROCKET_VERSION' ) ) {
add_filter( 'rocket_excluded_inline_js_content', [ $this, 'exclude_plausible_inline_js' ] );
add_filter( 'rocket_exclude_js', [ $this, 'exclude_plausible_js' ] );
add_filter( 'rocket_minify_excluded_external_js', [ $this, 'exclude_plausible_js' ] );
add_filter( 'rocket_delay_js_scripts', [ $this, 'exclude_plausible_js' ] );
// LiteSpeed Cache
if ( defined( 'LSCWP_V' ) ) {
add_filter( 'litespeed_optimize_js_excludes', [ $this, 'exclude_plausible_js' ] );
add_filter( 'litespeed_optm_js_defer_exc', [ $this, 'exclude_plausible_inline_js' ] );
add_filter( 'litespeed_optm_gm_js_exc', [ $this, 'exclude_plausible_inline_js' ] );
}

// SG Optimizer
Expand All @@ -41,20 +43,22 @@ public function __construct() {
add_filter( 'sgo_javascript_combine_excluded_external_paths', [ $this, 'exclude_plausible_js' ] );
}

// WPML
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
add_filter( 'rest_url', [ $this, 'wpml_compatibility' ], 10, 1 );
}

// WP Optimize
if ( defined( 'WPO_VERSION' ) ) {
add_filter( 'wp-optimize-minify-default-exclusions', [ $this, 'exclude_plausible_js' ] );
}

// LiteSpeed Cache
if ( defined( 'LSCWP_V' ) ) {
add_filter( 'litespeed_optimize_js_excludes', [ $this, 'exclude_plausible_js' ] );
add_filter( 'litespeed_optm_js_defer_exc', [ $this, 'exclude_plausible_inline_js' ] );
add_filter( 'litespeed_optm_gm_js_exc', [ $this, 'exclude_plausible_inline_js' ] );
}

if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
add_filter( 'rest_url', [ $this, 'wpml_compatibility' ], 10, 1 );
// WP Rocket
if ( defined( 'WP_ROCKET_VERSION' ) ) {
add_filter( 'rocket_excluded_inline_js_content', [ $this, 'exclude_plausible_inline_js' ] );
add_filter( 'rocket_exclude_js', [ $this, 'exclude_plausible_js' ] );
add_filter( 'rocket_minify_excluded_external_js', [ $this, 'exclude_plausible_js' ] );
add_filter( 'rocket_delay_js_scripts', [ $this, 'exclude_plausible_js' ] );
}
}

Expand Down
Loading

0 comments on commit 94e324b

Please sign in to comment.