Skip to content
Draft
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
4 changes: 4 additions & 0 deletions Helper/Conversion.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,12 @@ public function getCartData(): array
if ($order->getId()) {
$total = $displayPriceWithTax? $order->getGrandTotal() : $order->getSubtotal();
$result = [
'cart_id' => (string) $order->getQuoteId(),
'cart_value' => $this->rejoinerHelper->convertPriceToCents($total),
'cart_item_count' => intval($order->getTotalQtyOrdered()),
'queen_one_total_price' => $this->rejoinerHelper->convertPriceToCents($order->getGrandTotal()),
'queen_one_subtotal_price' => $this->rejoinerHelper->convertPriceToCents($order->getSubtotal()),
'currency_code' => (string) $order->getOrderCurrencyCode(),
'customer_order_number' => $order->getIncrementId(),
'return_url' => $this->_urlBuilder->getUrl('sales/order/view/', ['order_id' => $order->getIncrementId()])
];
Expand Down
43 changes: 43 additions & 0 deletions Helper/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
use Magento\SalesRule\Model\RuleFactory;
use \Magento\Store\Model\ScopeInterface;
use Monolog\Logger;
use Rejoiner\Acr\Model\System\Config\Source\FrontendTrackingMode;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
private const XML_PATH_REJOINER_ENABLED = 'checkout/rejoiner_acr/enabled';
private const XML_PATH_REJOINER_SITE_ID = 'checkout/rejoiner_acr/site_id';
private const XML_PATH_FRONTEND_TRACKING_MODE = 'checkout/rejoiner_acr/frontend_tracking_mode';
private const XML_PATH_QUEEN_ONE_TAG_URL = 'checkout/rejoiner_acr/queen_one_tag_url';
private const XML_PATH_REJOINER_DOMAIN = 'checkout/rejoiner_acr/domain';
private const XML_PATH_REJOINER_TRACK_NUMBERS = 'checkout/rejoiner_acr/track_numbers';
private const XML_PATH_REJOINER_TRACK_PRICE_WITH_TAX = 'checkout/rejoiner_acr/track_price_with_tax';
Expand Down Expand Up @@ -306,6 +309,46 @@ public function getRejoinerSiteId(): string
return (string) $this->scopeConfig->getValue(self::XML_PATH_REJOINER_SITE_ID, ScopeInterface::SCOPE_STORE);
}

public function getFrontendTrackingMode(): string
{
$mode = (string) $this->scopeConfig->getValue(
self::XML_PATH_FRONTEND_TRACKING_MODE,
ScopeInterface::SCOPE_STORE
);

return in_array(
$mode,
[FrontendTrackingMode::REJOINER, FrontendTrackingMode::DUAL, FrontendTrackingMode::QUEEN_ONE],
true
) ? $mode : FrontendTrackingMode::REJOINER;
}

public function isRejoinerFrontendEnabled(): bool
{
return in_array(
$this->getFrontendTrackingMode(),
[FrontendTrackingMode::REJOINER, FrontendTrackingMode::DUAL],
true
);
}

public function isQueenOneFrontendEnabled(): bool
{
return in_array(
$this->getFrontendTrackingMode(),
[FrontendTrackingMode::DUAL, FrontendTrackingMode::QUEEN_ONE],
true
);
}

public function getQueenOneTagUrl(): string
{
return trim((string) $this->scopeConfig->getValue(
self::XML_PATH_QUEEN_ONE_TAG_URL,
ScopeInterface::SCOPE_STORE
));
}

/**
* @return string
*/
Expand Down
7 changes: 6 additions & 1 deletion Helper/Snippets.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,13 @@ public function getCartData()
if ($quote->getAllVisibleItems()) {
$total = $displayPriceWithTax? $quote->getGrandTotal() : $quote->getSubtotal();
$result = [
'cart_id' => (string) $quote->getId(),
'total_items_count' => (string) intval($quote->getItemsQty()),
'cart_value' => (string) $this->rejoinerHelper->convertPriceToCents($total),
'queen_one_cart_value' => (string) $this->rejoinerHelper->convertPriceToCents(
$quote->getGrandTotal()
),
'currency_code' => (string) $quote->getQuoteCurrencyCode(),
'return_url' => (string) $this->rejoinerHelper->getRestoreUrl()
];
if ($this->rejoinerHelper->getIsEnabledCouponCodeGeneration()) {
Expand Down Expand Up @@ -115,4 +120,4 @@ protected function getQuote()
{
return $this->checkoutSession->getQuote();
}
}
}
25 changes: 25 additions & 0 deletions Model/System/Config/Source/FrontendTrackingMode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Rejoiner\Acr\Model\System\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;

class FrontendTrackingMode implements OptionSourceInterface
{
public const REJOINER = 'rejoiner';
public const DUAL = 'dual';
public const QUEEN_ONE = 'queen_one';

/**
* @return array<int, array{value: string, label: string}>
*/
public function toOptionArray(): array
{
return [
['value' => self::REJOINER, 'label' => __('Rejoiner')],
['value' => self::DUAL, 'label' => __('Rejoiner + Queen One (shadow)')],
['value' => self::QUEEN_ONE, 'label' => __('Queen One')],
];
}
}
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"magento/module-newsletter": ">=100.0.0"
},
"type": "magento2-module",
"version": "3.2.1",
"license": [
"OSL-3.0",
"AFL-3.0"
Expand All @@ -19,5 +18,10 @@
"psr-4": {
"Rejoiner\\Acr\\": ""
}
},
"extra": {
"branch-alias": {
"dev-queen-one": "4.x-dev"
}
}
}
18 changes: 18 additions & 0 deletions dev/magento/BASELINE_TEST_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ Evidence links or attachments:
| Cart recovery | Cart restored in disposable session | Not run | |
| Scheduled conversion | Deferred until cron defect is fixed | Blocked | Known legacy defect |

## Queen One shadow results

Frontend tracking mode:

Queen One tag URL:

| Scenario | Expected evidence | Result | Evidence / defect |
| --- | --- | --- | --- |
| Default mode | Only the existing Rejoiner frontend loads | Not run | |
| Dual mode page | `page_viewed`, `module_id: magento2` | Not run | |
| Product page | `product_viewed` with catalog-compatible product ID | Not run | |
| Cart mutation | One `cart_set` with full products and currency-aware Money values | Not run | |
| Empty cart | `cart_reset` | Not run | |
| Customer login | `user_identified` with synthetic email | Not run | |
| Checkout success | `order_created` with order ID, total and items | Not run | |
| Dual mode regression | Existing `_rejoiner` commands still appear | Not run | |
| Queen One mode | No `cdn.rejoiner.com` frontend script request | Not run | |

## Findings

### Confirmed behavior
Expand Down
33 changes: 33 additions & 0 deletions dev/magento/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,39 @@ Then inspect `window._rejoiner` while performing these actions:

Record the evidence in [BASELINE_TEST_REPORT.md](BASELINE_TEST_REPORT.md).

## Queen One shadow tracking

The long-lived `queen-one` branch is the migration lane for existing clients.
Once Packagist has indexed that branch, clients can pin it explicitly with:

composer require rejoiner/module-acr:"dev-queen-one"

The branch declares `dev-queen-one` as `4.x-dev`; stable clients remain on the
3.x tags until the Queen One implementation is complete and released.

For a local frontend proof, keep all customer data synthetic and configure:

bin/magento config:set checkout/rejoiner_acr/frontend_tracking_mode dual
bin/magento config:set checkout/rejoiner_acr/queen_one_tag_url \
https://queen-one-init-development.queen-one.workers.dev/queen-one.js
bin/magento cache:flush

`dual` keeps the current Rejoiner frontend active and additionally emits the
canonical Queen One events. In browser DevTools inspect `window.__qotag._q`
before the remote tag drains the queue, or filter Network requests by `track`.
Exercise these scenarios:

1. Any storefront page emits `page_viewed`.
2. A product page additionally emits `product_viewed`.
3. Add, update and remove cart items; `cart_set` contains the complete cart.
4. Log in with a synthetic customer; `user_identified` contains the email.
5. Place an offline-payment order; `order_created` contains the increment ID,
currency-aware total and complete items.

The development tag still needs a valid development site ID accepted by the
Event Collector. Queue inspection remains available if remote delivery is not
provisioned yet.

## Resetting the lab

The upstream generated lab contains destructive removal helpers. They are not
Expand Down
6 changes: 6 additions & 0 deletions dev/magento/smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ if bin/cli test -e app/code/Rejoiner/Acr/.local/magento; then
exit 1
fi
bin/cli php -l app/code/Rejoiner/Acr/Helper/Data.php >/dev/null
bin/cli php -l app/code/Rejoiner/Acr/Helper/Snippets.php >/dev/null
bin/cli php -l app/code/Rejoiner/Acr/Helper/Conversion.php >/dev/null
bin/cli php -l app/code/Rejoiner/Acr/Model/System/Config/Source/FrontendTrackingMode.php >/dev/null
bin/cli php -l app/code/Rejoiner/Acr/Observer/ControllerActionPredispatch.php >/dev/null
echo "PASS: generated lab is masked from the module mount"

echo "Checking Composer metadata..."
bin/cli composer validate --no-check-all app/code/Rejoiner/Acr/composer.json

echo "Checking module and Magento schema status..."
bin/magento module:status Rejoiner_Acr
bin/magento setup:db:status
Expand Down
19 changes: 18 additions & 1 deletion etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@
<field id="enabled">1</field>
</depends>
</field>
<field id="frontend_tracking_mode" translate="label comment" type="select" sortOrder="6" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Frontend Tracking Mode</label>
<comment>Use dual mode to validate Queen One tracking while keeping the current Rejoiner frontend active.</comment>
<source_model>Rejoiner\Acr\Model\System\Config\Source\FrontendTrackingMode</source_model>
<depends>
<field id="enabled">1</field>
</depends>
</field>
<field id="queen_one_tag_url" translate="label comment" type="text" sortOrder="7" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Queen One Tag URL</label>
<comment>Use the approved Queen One development or production queen-one.js URL.</comment>
<validate>required-entry validate-url</validate>
<depends>
<field id="enabled">1</field>
<field id="frontend_tracking_mode" separator=",">dual,queen_one</field>
</depends>
</field>
<field id="api_key" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Rejoiner API key</label>
<validate>required-entry</validate>
Expand Down Expand Up @@ -288,4 +305,4 @@
</group>
</section>
</system>
</config>
</config>
3 changes: 2 additions & 1 deletion etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<default>
<checkout>
<rejoiner_acr>
<frontend_tracking_mode>rejoiner</frontend_tracking_mode>
<process_by_cron>1</process_by_cron>
<thumbnail_size_width>200</thumbnail_size_width>
<thumbnail_size_height>200</thumbnail_size_height>
Expand All @@ -20,4 +21,4 @@
</rejoiner_acr>
</checkout>
</default>
</config>
</config>
9 changes: 9 additions & 0 deletions etc/csp_whitelist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@
<policy id="script-src">
<values>
<value id="rejoiner" type="host">*.rejoiner.com</value>
<value id="queen-one" type="host">*.queen.one</value>
<value id="queen-one-init-development" type="host">queen-one-init-development.queen-one.workers.dev</value>
<value id="queen-one-core-development" type="host">queen-one-core-development.queen-one.workers.dev</value>
</values>
</policy>
<policy id="connect-src">
<values>
<value id="rejoiner" type="host">*.rejoiner.com</value>
<value id="queen-one" type="host">*.queen.one</value>
</values>
</policy>
<policy id="frame-src">
<values>
<value id="queen-one" type="host">*.queen.one</value>
</values>
</policy>
</policies>
Expand Down
5 changes: 3 additions & 2 deletions view/frontend/requirejs-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
var config = {
map: {
'*': {
RejoinerAcrTracking : 'Rejoiner_Acr/js/tracking'
RejoinerAcrTracking : 'Rejoiner_Acr/js/tracking',
QueenOneTracking : 'Rejoiner_Acr/js/queen-one'
}
},
config: {
Expand All @@ -15,4 +16,4 @@ var config = {
}
}
}
};
};
13 changes: 11 additions & 2 deletions view/frontend/templates/rejoiner_acr/base.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ foreach ($childBlockNames as $childBlockName) {
}
}
?>
<?php if ($rejoinerHelper->getRejoinerSiteId() && $rejoinerHelper->getDomain()) : ?>
<?php if (
$rejoinerHelper->getRejoinerSiteId()
&& (
($rejoinerHelper->isRejoinerFrontendEnabled() && $rejoinerHelper->getDomain())
|| $rejoinerHelper->isQueenOneFrontendEnabled()
)
) : ?>
<?php
$domain = $escaper->escapeHtml($rejoinerHelper->getDomain());
$siteId = $escaper->escapeHtml($rejoinerHelper->getRejoinerSiteId());
$rejoinerScriptUri = $escaper->escapeHtml($rejoinerHelper->getRejoinerScriptUri());
$frontendTrackingMode = $escaper->escapeHtml($rejoinerHelper->getFrontendTrackingMode());
$queenOneTagUrl = $escaper->escapeHtml($rejoinerHelper->getQueenOneTagUrl());
?>
<script type="text/x-magento-init">
{
Expand All @@ -33,6 +41,8 @@ foreach ($childBlockNames as $childBlockName) {
"rejoinerSiteId" : "<?= $siteId ?>",
"rejoinerDomain" : "<?= $domain ?>",
"rejoinerScriptUri" : "<?= $rejoinerScriptUri ?>",
"frontendTrackingMode" : "<?= $frontendTrackingMode ?>",
"queenOneTagUrl" : "<?= $queenOneTagUrl ?>",
"trackNumberEnabled" : <?= $escaper->escapeHtml($rejoinerHelper->getTrackNumberEnabled()) ?>,
"persistFormsEnabled" : <?= $escaper->escapeHtml($rejoinerHelper->getPersistFormsEnabled()) ?>,
"trackCartDataOnThisPage" : <?=
Expand All @@ -44,4 +54,3 @@ foreach ($childBlockNames as $childBlockName) {
}
</script>
<?php endif ?>

Loading