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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2026-08-05 5.0.15
* Fix cart tracking event payload and cart ID lifecycle

## 2026-06-18 5.0.14
* WordPress 7.0 compatibility: updated Tested up to
* Fixed jQuery dependency registration for plugin scripts
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.0.14
5.0.15
32 changes: 17 additions & 15 deletions src/assets/js/retailcrm-tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,23 @@ function startTrack(...trackerEvents)

function sendCartChange()
{
let cart = {};
cart.items = [];

getCartItems().then(function(cartItems) {
cartItems.forEach(item => {
cart.items.push({
external_id: item.id,
xml_id: item.sku,
price: item.price,
quantity: item.quantity
});
});
});
getCartItems().then(function(response) {
if (!response?.cart_id || !Array.isArray(response.items) || response.items.length === 0) {
return;
}

const cart = {
cart_id: response.cart_id,
items: response.items.map(function(item) {
return {
external_id: item.id,
xml_id: item.sku,
price: item.price,
quantity: item.quantity
};
})
};

if (cart.items !== []) {
getCustomerInfo().then(function (customer) {
if (!customer?.externalId) {
return;
Expand All @@ -93,7 +95,7 @@ function startTrack(...trackerEvents)
ocapi.event('cart', cart);
}, 1000);
});
}
});
}

async function getCustomerInfo() {
Expand Down
36 changes: 35 additions & 1 deletion src/include/class-wc-retailcrm-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
class WC_Retailcrm_Base extends WC_Retailcrm_Abstracts_Settings
{
const ASSETS_DIR = '/woo-retailcrm/assets';
const TRACKER_CART_ID_SESSION_KEY = 'retailcrm_tracker_cart_id';

/** @var WC_Retailcrm_Proxy|WC_Retailcrm_Client_V5|bool */
protected $apiClient;
Expand Down Expand Up @@ -195,6 +196,16 @@ public function __construct($retailcrm = false)
}

function get_cart_items_for_tracker()
{
wp_send_json_success($this->get_cart_data_for_tracker());
}

/**
* Get the current cart data for the JS tracker.
*
* @return array
*/
public function get_cart_data_for_tracker()
{
$cartItems = [];

Expand All @@ -209,7 +220,26 @@ function get_cart_items_for_tracker()
];
}

wp_send_json_success($cartItems);
$cartId = null;
$session = WC()->session;

if (empty($cartItems)) {
if ($session) {
$session->__unset(self::TRACKER_CART_ID_SESSION_KEY);
}
} elseif ($session) {
$cartId = $session->get(self::TRACKER_CART_ID_SESSION_KEY);

if (empty($cartId)) {
$cartId = wp_generate_uuid4();
$session->set(self::TRACKER_CART_ID_SESSION_KEY, $cartId);
}
}

return [
'cart_id' => $cartId,
'items' => $cartItems,
];
}

function get_customer_info_for_tracker()
Expand Down Expand Up @@ -531,6 +561,10 @@ public function retailcrm_process_order($order_id)

WC_Retailcrm_Logger::setHook(current_action(), $order_id);
$this->orders->orderCreate($order_id);

if (WC()->session) {
WC()->session->__unset(self::TRACKER_CART_ID_SESSION_KEY);
}
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Tags: crm, marketing, e-com
Requires PHP: 7.1
Requires at least: 5.3
Tested up to: 7.0
Stable tag: 5.0.14
Stable tag: 5.0.15
License: MIT
License URI: https://github.com/retailcrm/woocommerce-module/blob/master/LICENSE

Expand Down Expand Up @@ -47,6 +47,9 @@ Make sure you have a specific API key must for each store.

== Changelog ==

= 5.0.15 =
* Fix cart tracking event payload and cart ID lifecycle

= 5.0.14 =
* WordPress 7.0 compatibility

Expand Down
2 changes: 1 addition & 1 deletion src/uninstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @link https://wordpress.org/plugins/woo-retailcrm/
*
* @version 5.0.14
* @version 5.0.15
*
* @package RetailCRM
*/
Expand Down
4 changes: 2 additions & 2 deletions src/woo-retailcrm.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Author URI: http://retailcrm.pro/
* License: MIT
* License URI: https://github.com/retailcrm/woocommerce-module/blob/master/LICENSE
* Version: 5.0.14
* Version: 5.0.15
* Tested up to: 7.0
* Requires Plugins: woocommerce
* WC requires at least: 5.4
Expand All @@ -30,7 +30,7 @@
class WC_Integration_Retailcrm {
const WOOCOMMERCE_SLUG = 'woocommerce';
const WOOCOMMERCE_PLUGIN_PATH = 'woocommerce/woocommerce.php';
const MODULE_VERSION = '5.0.14';
const MODULE_VERSION = '5.0.15';

private static $instance;

Expand Down
65 changes: 65 additions & 0 deletions tests/test-wc-retailcrm-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,71 @@ public function test_subscribed_checkbox()
ob_end_clean();
}

public function test_cart_id_lifecycle()
{
$product = WC_Helper_Product::create_simple_product();
$product->set_sku('SKU-123');
$product->set_regular_price(159);
$product->set_price(159);
$product->save();

WC()->cart->empty_cart();
WC()->session->__unset(WC_Retailcrm_Base::TRACKER_CART_ID_SESSION_KEY);
WC()->cart->add_to_cart($product->get_id(), 2);

$initialCart = $this->baseRetailcrm->get_cart_data_for_tracker();

$this->assertNotEmpty($initialCart['cart_id']);
$this->assertTrue(wp_is_uuid($initialCart['cart_id']));
$this->assertCount(1, $initialCart['items']);
$this->assertEquals((string) $product->get_id(), $initialCart['items'][0]['id']);
$this->assertEquals('SKU-123', $initialCart['items'][0]['sku']);
$this->assertEquals(wc_get_price_including_tax($product), $initialCart['items'][0]['price']);
$this->assertEquals(2, $initialCart['items'][0]['quantity']);

$updatedCart = $this->baseRetailcrm->get_cart_data_for_tracker();

$this->assertEquals($initialCart['cart_id'], $updatedCart['cart_id']);

WC()->cart->empty_cart();
$emptyCart = $this->baseRetailcrm->get_cart_data_for_tracker();

$this->assertNull($emptyCart['cart_id']);
$this->assertSame([], $emptyCart['items']);
$this->assertNull(WC()->session->get(WC_Retailcrm_Base::TRACKER_CART_ID_SESSION_KEY));

WC()->cart->add_to_cart($product->get_id());
$newCart = $this->baseRetailcrm->get_cart_data_for_tracker();

$this->assertNotEquals($initialCart['cart_id'], $newCart['cart_id']);

WC()->cart->empty_cart();
WC()->session->__unset(WC_Retailcrm_Base::TRACKER_CART_ID_SESSION_KEY);
}

public function test_cart_id_cleared_after_checkout()
{
$orders = $this
->getMockBuilder('\WC_Retailcrm_Orders')
->disableOriginalConstructor()
->setMethods(['orderCreate'])
->getMock();
$orders
->expects($this->once())
->method('orderCreate')
->with(123);

$ordersProperty = new ReflectionProperty(WC_Retailcrm_Base::class, 'orders');
$ordersProperty->setAccessible(true);
$ordersProperty->setValue($this->baseRetailcrm, $orders);

WC()->session->set(WC_Retailcrm_Base::TRACKER_CART_ID_SESSION_KEY, wp_generate_uuid4());

$this->baseRetailcrm->retailcrm_process_order(123);

$this->assertNull(WC()->session->get(WC_Retailcrm_Base::TRACKER_CART_ID_SESSION_KEY));
}

public function test_initialize_whatsapp()
{
ob_start();
Expand Down
Loading