Skip to content
Closed
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
99 changes: 62 additions & 37 deletions facebook_pixel_tracking/static/src/js/website_sale_tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,74 +13,99 @@ publicWidget.registry.FacebookPixelTracking = publicWidget.Widget.extend({
"click a.on_checkout_start_js": "_onCheckoutStartJs",
},

_pushInfo: function (event, dict){
if(typeof(fbq) !== 'undefined'){
_pushInfo: function (event, dict) {
if (typeof fbq !== 'undefined') {
fbq('track', event, dict);
console.log(dict);
}
console.log(event,dict);
},
_onClickAddToCartProduct: function (ev){

_onClickAddToCartProduct: function (ev) {
var dataTarget = ev.target.closest('a#add_to_cart');
var product_id = dataTarget.dataset.product_id;
var product_sku = dataTarget.dataset.product_sku;
var product_name = dataTarget.dataset.product_name;
var product_price = dataTarget.dataset.product_price;
var product_amount = $("[name=add_qty]").val();
var amount = parseFloat(product_price * product_amount).toFixed(2);
var product_price = parseFloat(dataTarget.dataset.product_price) || 0;
var currency = dataTarget.dataset.currency;
const dict = {
'content_name': product_name,
'content_ids': [product_id],
'content_type': 'product',
'value': product_price,
'total': amount,
}
content_name: product_name,
content_ids: [String(product_sku || product_id)],
content_type: 'product',
value: product_price,
currency: currency,
};
this._pushInfo('AddToCart', dict);
},
_onClickAddToCartProductsItem: function(ev) {

_onClickAddToCartProductsItem: function (ev) {
var dataTarget = ev.target.closest('div.o_wsale_product_btn');
var product_id = dataTarget.dataset.product_id;
var product_sku = dataTarget.dataset.product_sku;
var product_name = dataTarget.dataset.product_name;
var product_price = dataTarget.dataset.product_price;
var product_price = parseFloat(dataTarget.dataset.product_price) || 0;
const dict = {
'content_name': product_name,
'content_ids': [product_sku || product_id],
'content_type': 'product',
'value': product_price,
}
content_name: product_name,
content_ids: [String(product_sku || product_id)],
content_type: 'product',
value: product_price,
};
this._pushInfo('AddToCart', dict);
},

_onCheckoutStartJs: function () {
var dataTarget = $("#cart_products")[0];
const info = dataTarget.dataset.cart_info;
const dict = {
'event':'begin_checkout',
'ecommerce':{'items':info}
const items = JSON.parse(dataTarget.dataset.cart_info || '[]');
const contents = items
.filter(item => !item.is_reward_line)
.map(item => ({
id: String(item.item_id),
quantity: item.quantity,
item_price: item.price,
}));
if (!contents.length) {
return;
}
this._pushInfo('OnCheckoutStart', dict);
const dict = {
content_ids: contents.map(item => item.id),
content_type: 'product',
contents: contents,
num_items: contents.length,
value: parseFloat(dataTarget.dataset.value) || 0,
currency: dataTarget.dataset.currency,
};
this._pushInfo('InitiateCheckout', dict);
},
});

//Heredamos PaymentForm form porque el metodo _submitForm tiene stopPropagation y preventDefault, impidiendonos hacerlo en el widget GoogleTagManagerAdvancedTracking
// Heredamos PaymentForm porque el método _submitForm tiene stopPropagation y preventDefault,
// impidiéndonos capturarlo desde el widget FacebookPixelTracking.
PaymentForm.include({

_pushInfo: function (event, dict){
if(typeof(fbq) !== 'undefined'){
_pushInfo: function (event, dict) {
if (typeof fbq !== 'undefined') {
fbq('track', event, dict);
console.log(dict);
}
},

// @override
_submitForm: async function (ev) {
const info_div = $("#o_wsale_accordion_item")[0]
if(info_div){
const info = info_div.dataset.purchase_info;
const info_div = $("#o_wsale_accordion_item")[0];
if (info_div) {
const info = JSON.parse(info_div.dataset.purchase_info || '{}');
const contents = (info.items || []).map(item => ({
id: String(item.item_id),
quantity: item.quantity,
item_price: item.price,
}));
const dict = {
'event':'purchase',
'ecommerce':info
}
this._pushInfo(dict);
value: info.value,
currency: info.currency,
content_ids: contents.map(item => item.id),
contents: contents,
content_type: 'product',
};
this._pushInfo('Purchase', dict);
}
this._super(...arguments);
await this._super(...arguments);
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ publicWidget.registry.GoogleTagManagerAdvancedTracking = publicWidget.Widget.ext
_onClickAddToCartProduct: function (ev) {
var dataTarget = ev.target.closest('a#add_to_cart');
var product_id = dataTarget.dataset.product_id;
var product_sku = dataTarget.dataset.product_sku;
var product_name = dataTarget.dataset.product_name;
var currency = dataTarget.dataset.currency;
var product_price = dataTarget.dataset.product_price;
var product_amount = $("[name=add_qty]").val();
var product_amount = $('[name=add_qty]').val();
var amount = parseFloat(product_price * product_amount).toFixed(2);
const dict = {
'event': 'add_to_cart',
Expand All @@ -58,7 +59,7 @@ publicWidget.registry.GoogleTagManagerAdvancedTracking = publicWidget.Widget.ext
'value': amount,
'items': [{
'item_name': product_name,
'item_id': product_id,
'item_id': product_sku || product_id,
'price': product_price,
'quantity': product_amount,
}]
Expand Down Expand Up @@ -89,26 +90,37 @@ publicWidget.registry.GoogleTagManagerAdvancedTracking = publicWidget.Widget.ext
},
_onCheckoutStartJs: function () {
var dataTarget = $("#cart_products")[0];
if( Object.keys(dataTarget.dataset).length > 0) {
if(dataTarget && Object.keys(dataTarget.dataset).length > 0) {
try {
var dataTarget = $("#cart_products")[0];
var currency = dataTarget.dataset.currency;
var value = dataTarget.dataset.value;
const info_string = dataTarget.dataset.cart_info;

// Robust parsing
let jsonString = info_string.replace(/\\/g, '\\\\').replace(/\'/g, '"');
jsonString = jsonString.replace(/:\s*None([,\}])/g, ': null$1');
jsonString = jsonString.replace(/:\s*True([,\}])/g, ': true$1');
jsonString = jsonString.replace(/:\s*False([,\}])/g, ': false$1');

const info = JSON.parse(jsonString);
const info = JSON.parse(info_string || '[]');
const allLines = Array.isArray(info) ? info : (info.items || []);
const rewardTotal = allLines
.filter((line) => line && line.is_reward_line)
.reduce((sum, line) => {
const price = Number(line.price || 0);
const quantity = Number(line.quantity || 1);
return sum + (price * quantity);
}, 0);
const items = allLines
.filter((line) => line && !line.is_reward_line)
.map((line) => ({
item_name: line.item_name,
item_id: line.item_id,
price: line.price,
quantity: line.quantity,
}));
const dict = {
'event':'begin_checkout',
'ecommerce':{
'currency': currency,
'value': value,
'items':info
'value': Number(value || 0),
'discount': Math.abs(rewardTotal),
'items': items,
}
}
this._pushInfo(dict);
Expand Down Expand Up @@ -144,16 +156,7 @@ publicWidget.registry.GoogleTagManagerAdvancedTracking = publicWidget.Widget.ext
const cart = element[0]
if(cart){
const info_string = element[0].dataset.cart_info;
// Attempt to fix common Python dict string issues for JSON parsing
// 1. Escape existing backslashes
// 2. Replace single quotes with doublequotes
// 3. Replace Python boolean/none literals (only when they appear as values)
let jsonString = info_string.replace(/\\/g, '\\\\').replace(/\'/g, '"');
jsonString = jsonString.replace(/:\s*None([,\}])/g, ': null$1');
jsonString = jsonString.replace(/:\s*True([,\}])/g, ': true$1');
jsonString = jsonString.replace(/:\s*False([,\}])/g, ': false$1');

const info = JSON.parse(jsonString);
const info = JSON.parse(info_string || '{}');
const dict = {
'event': 'view_cart',
'ecommerce': info
Expand All @@ -169,13 +172,17 @@ publicWidget.registry.GoogleTagManagerAdvancedTracking = publicWidget.Widget.ext
try {
const info_string = confirmation.data('purchase_info');

// Robust parsing
let jsonString = info_string.replace(/\\/g, '\\\\').replace(/\'/g, '"');
jsonString = jsonString.replace(/:\s*None([,\}])/g, ': null$1');
jsonString = jsonString.replace(/:\s*True([,\}])/g, ': true$1');
jsonString = jsonString.replace(/:\s*False([,\}])/g, ': false$1');

const info = JSON.parse(jsonString);
// jQuery .data() auto-parses valid JSON into an object, handle both cases
let info;
if (typeof info_string === 'object') {
info = info_string;
} else {
let jsonString = info_string.replace(/\\/g, '\\\\').replace(/\'/g, '"');
jsonString = jsonString.replace(/:\s*None([,\}])/g, ': null$1');
jsonString = jsonString.replace(/:\s*True([,\}])/g, ': true$1');
jsonString = jsonString.replace(/:\s*False([,\}])/g, ': false$1');
info = JSON.parse(jsonString);
}
const dict = {
'event': 'purchase',
'ecommerce': info
Expand Down
31 changes: 21 additions & 10 deletions website_sale_advanced_tracking/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from odoo import models


Expand All @@ -6,21 +8,30 @@ class SaleOrder(models.Model):

def prepare_purchase_information(self):
products = []
discount = 0.0
shipping = 0.0
for line in self.order_line:
products.append(
{
"item_id": line.product_id.default_code or line.product_id.id,
"item_name": line.product_id.name,
"item_category": line.product_id.categ_id.name,
"quantity": line.product_uom_qty,
"price": line.price_reduce_taxinc,
}
)
if getattr(line, "is_reward_line", False):
discount += abs(line.price_reduce_taxinc * line.product_uom_qty)
elif getattr(line, "is_delivery", False):
shipping += line.price_reduce_taxinc * line.product_uom_qty
else:
products.append(
{
"item_id": line.product_id.default_code or line.product_id.id,
"item_name": line.product_id.name,
"item_category": line.product_id.categ_id.name,
"quantity": line.product_uom_qty,
"price": line.price_reduce_taxinc,
}
)
res = {
"transaction_id": self.id,
"value": self.amount_total,
"tax": self.amount_tax,
"shipping": shipping,
"discount": discount,
"currency": self.currency_id.name,
"items": products,
}
return res
return json.dumps(res)
9 changes: 6 additions & 3 deletions website_sale_advanced_tracking/models/sale_order_line.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from odoo import models


Expand All @@ -9,10 +11,11 @@ def prepare_checkout_information(self):
for line in self:
res.append(
{
"item_name": line.name,
"item_name": line.product_id.name,
"item_id": line.product_id.default_code or line.product_id.id,
"price": (line.price_reduce_taxinc),
"price": line.price_reduce_taxinc,
"quantity": line.product_uom_qty,
"is_reward_line": getattr(line, "is_reward_line", False),
}
)
return res
return json.dumps(res)
4 changes: 2 additions & 2 deletions website_sale_advanced_tracking/views/templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<odoo>
<template id="product" inherit_id="website_sale.product">
<xpath expr="//a[@id='add_to_cart']" position="attributes">
<attribute name="t-att-data-product_id">product.default_code</attribute>
<attribute name="t-att-data-product_id">product.id</attribute>
<attribute name="t-att-data-product_name">product.name</attribute>
<attribute name="t-att-data-product_price">combination_info['price']</attribute>
<attribute name="t-att-data-product_sku">product.default_code</attribute>
Expand Down Expand Up @@ -35,7 +35,7 @@
</xpath>
</template>
<template id="cart_lines" inherit_id="website_sale.cart_lines">
<xpath expr="//div[@id='cart_products']" position="attributes">
<xpath expr="//*[@id='cart_products']" position="attributes">
<attribute name="t-att-data-cart_info">website_sale_order.website_order_line.prepare_checkout_information()</attribute>
<attribute name="t-att-data-currency">website.currency_id.name</attribute>
<attribute name="t-att-data-value">website_sale_order.amount_total</attribute>
Expand Down
Loading