Skip to content

Commit

Permalink
Merge pull request #2734 from woocommerce/fix/2733-prevent-duplicate-…
Browse files Browse the repository at this point in the history
…purchase-event-tracking

Prevent duplicate conversion and purchase event tracking
  • Loading branch information
mikkamp authored Dec 18, 2024
2 parents 91e2945 + c43a34d commit 03a3290
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/Google/GlobalSiteTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ function () use ( $gtag_events, $wp_consent_api ) {
public function activate_global_site_tag( string $ads_conversion_id ) {
if ( $this->gtag_js->is_adding_framework() ) {
if ( $this->gtag_js->ga4w_v2 ) {
wp_add_inline_script(
$this->wp->wp_add_inline_script(
'woocommerce-google-analytics-integration',
$this->get_gtag_config( $ads_conversion_id )
);
Expand Down Expand Up @@ -331,12 +331,12 @@ protected function get_consent_mode_config() {
*/
public function add_inline_event_script( string $inline_script ) {
if ( class_exists( '\WC_Google_Gtag_JS' ) ) {
wp_add_inline_script(
$this->wp->wp_add_inline_script(
'woocommerce-google-analytics-integration',
$inline_script
);
} else {
wp_print_inline_script_tag( $inline_script );
$this->wp->wp_print_inline_script_tag( $inline_script );
}
}

Expand All @@ -355,7 +355,7 @@ public function maybe_display_conversion_and_purchase_event_snippets( string $ad

$order = wc_get_order( $order_id );
// Make sure there is a valid order object and it is not already marked as tracked
if ( ! $order || 1 === $order->get_meta( self::ORDER_CONVERSION_META_KEY, true ) ) {
if ( ! $order || 1 === (int) $order->get_meta( self::ORDER_CONVERSION_META_KEY, true ) ) {
return;
}

Expand Down
22 changes: 22 additions & 0 deletions src/Proxies/WP.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,26 @@ public function wp_update_image_subsizes( int $attachment_id ) {
public function wp_remote_get( string $url, array $args = [] ) {
return wp_remote_get( $url, $args );
}

/**
* Adds extra code to a registered script.
*
* @param string $handle Name of the script to add the inline script to.
* @param string $data String containing the JavaScript to be added.
* @param string $position Whether to add the inline script before the handle or after. Default 'after'.
* @return boolean
*/
public function wp_add_inline_script( string $handle, string $data, string $position = 'after' ): bool {
return wp_add_inline_script( $handle, $data, $position );
}

/**
* Prints an inline script tag.
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Key-value pairs representing <script> tag attributes. Default:array()
*/
public function wp_print_inline_script_tag( string $data, array $attributes = [] ) {
return wp_print_inline_script_tag( $data, $attributes );
}
}
113 changes: 113 additions & 0 deletions tests/Unit/Google/GlobalSiteTagTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php
declare( strict_types=1 );

namespace Automattic\WooCommerce\GoogleListingsAndAds\Tests\Unit\Google;

use Automattic\WooCommerce\GoogleListingsAndAds\Assets\AssetsHandlerInterface;
use Automattic\WooCommerce\GoogleListingsAndAds\Google\GlobalSiteTag;
use Automattic\WooCommerce\GoogleListingsAndAds\Product\ProductHelper;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\GoogleGtagJs;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WC;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WP;
use Automattic\WooCommerce\GoogleListingsAndAds\Tests\Framework\UnitTest;
use PHPUnit\Framework\MockObject\MockObject;
use WC_Helper_Order;

defined( 'ABSPATH' ) || exit;

/**
* Class GlobalSiteTagTest
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Tests\Unit\Google
*/
class GlobalSiteTagTest extends UnitTest {

/** @var MockObject|AssetsHandlerInterface $assets_handler */
protected $assets_handler;

/** @var MockObject|GoogleGtagJs $gtag_js */
protected $gtag_js;

/** @var MockObject|ProductHelper $product_helper */
protected $product_helper;

/** @var MockObject|WC $wc */
protected $wc;

/** @var MockObject|WP $wp */
protected $wp;

/** @var GlobalSiteTag $tag */
protected $tag;

protected const TEST_CONVERSION_ID = 'test_id';
protected const TEST_CONVERSION_LABEL = 'test_conversion_label';

/**
* Runs before each test is executed.
*/
public function setUp(): void {
parent::setUp();

$this->assets_handler = $this->createMock( AssetsHandlerInterface::class );
$this->gtag_js = $this->createMock( GoogleGtagJs::class );
$this->product_helper = $this->createMock( ProductHelper::class );
$this->wc = $this->createMock( WC::class );
$this->wp = $this->createMock( WP::class );

$this->tag = new GlobalSiteTag( $this->assets_handler, $this->gtag_js, $this->product_helper, $this->wc, $this->wp );
}

public function test_conversion_and_purchase_event_not_order_received_page() {
add_filter( 'woocommerce_is_order_received_page', '__return_false' );
$this->wp->expects( $this->never() )->method( 'wp_print_inline_script_tag' );

$this->tag->maybe_display_conversion_and_purchase_event_snippets( self::TEST_CONVERSION_ID, self::TEST_CONVERSION_LABEL, 0 );
}

public function test_conversion_and_purchase_event_no_order() {
add_filter( 'woocommerce_is_order_received_page', '__return_true' );
$this->wp->expects( $this->never() )->method( 'wp_print_inline_script_tag' );

$this->tag->maybe_display_conversion_and_purchase_event_snippets( self::TEST_CONVERSION_ID, self::TEST_CONVERSION_LABEL, 0 );
}

public function test_conversion_and_purchase_event_already_tracked() {
add_filter( 'woocommerce_is_order_received_page', '__return_true' );

$order = WC_Helper_Order::create_order();
$order->update_meta_data( '_gla_tracked', 1 );
$order->save_meta_data();

$this->wp->expects( $this->never() )->method( 'wp_print_inline_script_tag' );

$this->tag->maybe_display_conversion_and_purchase_event_snippets( self::TEST_CONVERSION_ID, self::TEST_CONVERSION_LABEL, $order->get_id() );
}

public function test_conversion_and_purchase_event() {
add_filter( 'woocommerce_is_order_received_page', '__return_true' );

$order = WC_Helper_Order::create_order();

$invoked_count = $this->exactly( 2 );
$this->wp->expects( $invoked_count )
->method( 'wp_print_inline_script_tag' )
->willReturnCallback(
function ( string $script ) use ( $invoked_count ) {
if ( 1 === $invoked_count->getInvocationCount() ) {
$this->assertStringStartsWith( 'gtag("event", "conversion"', $script );
}

if ( 2 === $invoked_count->getInvocationCount() ) {
$this->assertStringStartsWith( 'gtag("event", "purchase"', $script );
}
}
);

$this->tag->maybe_display_conversion_and_purchase_event_snippets( self::TEST_CONVERSION_ID, self::TEST_CONVERSION_LABEL, $order->get_id() );

// Reload order and confirm tracked meta is set.
$order = wc_get_order( $order->get_id() );
$this->assertSame( 1, (int) $order->get_meta( '_gla_tracked', true ) );
}
}
1 change: 1 addition & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function () {
require_once $wc_tests_dir . '/framework/helpers/class-wc-helper-product.php';
require_once $wc_tests_dir . '/framework/helpers/class-wc-helper-shipping.php';
require_once $wc_tests_dir . '/framework/helpers/class-wc-helper-customer.php';
require_once $wc_tests_dir . '/framework/helpers/class-wc-helper-order.php';
require_once $wc_tests_dir . '/framework/vendor/class-wp-test-spy-rest-server.php';

/**
Expand Down

0 comments on commit 03a3290

Please sign in to comment.