Skip to content

Commit 7e74887

Browse files
authored
Merge pull request #325 from spring-media/TIPPI-896_cmp_list_align
feat[TIPPI-896]: conversion extension
2 parents 7ab98b2 + 6187aff commit 7e74887

File tree

4 files changed

+604
-82
lines changed

4 files changed

+604
-82
lines changed

extensions/kilkaya/k5a_meta_conversion.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Pre Loader — k5aMeta conversion for checkout success */
2-
/* global utag, a, b */
2+
/* global a, b */
33
/* eslint-disable-next-line no-unused-vars */
44
(function (a, b) {
55
try {
@@ -24,13 +24,8 @@
2424
window.k5aMeta.cntTag.push('offer_' + String(b.offer_id));
2525
}
2626

27-
if (window.utag && window.utag.cfg && window.utag.cfg.utDebug) {
28-
utag.DB('k5aMeta conversion set for checkout success');
29-
}
30-
3127
} catch (e) {
32-
if (window.utag && window.utag.cfg && window.utag.cfg.utDebug) {
33-
utag.DB('k5aMeta conversion error: ' + e);
34-
}
28+
// Silent error handling - conversion tracking should not break page functionality
29+
console.error('[K5A CONVERSION] Error:', e);
3530
}
3631
})(a, b);
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* Post Loader — Send Kilkaya conversion tracking */
2+
/* global a, b */
3+
/* eslint-disable-next-line no-unused-vars */
4+
(function (a, b) {
5+
try {
6+
if (String(b.event_name) !== 'checkout' || String(b.event_action) !== 'success') {
7+
return;
8+
}
9+
10+
// Helper to log to localStorage (survives redirect)
11+
var persistLog = function(message, data) {
12+
try {
13+
var log = {
14+
timestamp: new Date().toISOString(),
15+
message: message,
16+
data: data
17+
};
18+
localStorage.setItem('k5a_send_log', JSON.stringify(log));
19+
console.log('[K5A SEND] ' + message, data);
20+
} catch (e) {
21+
console.log('[K5A SEND] ' + message, data);
22+
}
23+
};
24+
25+
persistLog('Checkout success detected', {k5aMeta: window.k5aMeta});
26+
27+
// Wait for k5aMeta.conversion to be set by conversion extension
28+
setTimeout(function() {
29+
try {
30+
// Build the tracking URL manually based on Kilkaya's format
31+
var installationId = '68ee5be64709bd7f4b3e3bf2';
32+
var baseUrl = 'https://cl-eu10.k5a.io/';
33+
34+
// Get page data and utag data
35+
var pageData = window.k5aMeta || {};
36+
var U = (window.utag && window.utag.data) || {};
37+
38+
// Build query parameters for Kilkaya
39+
var params = [];
40+
params.push('i=' + encodeURIComponent(installationId));
41+
params.push('l=p'); // pageview log type
42+
params.push('cs=1'); // conversion status = 1
43+
params.push('nopv=1'); // Don't log as pageview, only sale
44+
params.push('_s=conversion');
45+
params.push('_m=b'); // method=beacon
46+
47+
// REQUIRED: Add URL parameter (u=)
48+
var url = pageData.url || U['dom.url'] || document.URL;
49+
if (url) {
50+
params.push('u=' + encodeURIComponent(url));
51+
}
52+
53+
// Add channel/platform (c=desktop|mobile)
54+
var platform = U.page_platform || U['cp.utag_main_page_platform'] || '';
55+
if (platform) {
56+
// Normalize platform value to desktop or mobile
57+
var channel = (platform.toLowerCase() === 'mobile') ? 'mobile' : 'desktop';
58+
params.push('c=' + encodeURIComponent(channel));
59+
}
60+
61+
// Add conversion-specific data
62+
if (pageData.conversion) params.push('cv=' + pageData.conversion);
63+
if (pageData.cntTag && Array.isArray(pageData.cntTag) && pageData.cntTag.length > 0) {
64+
params.push('cntt=' + encodeURIComponent(pageData.cntTag.join(',')));
65+
}
66+
67+
var trackingUrl = baseUrl + '?' + params.join('&');
68+
69+
persistLog('Tracking URL built', {url: trackingUrl});
70+
71+
// Try sendBeacon first (best for page unloads)
72+
if (navigator.sendBeacon) {
73+
var sent = navigator.sendBeacon(trackingUrl);
74+
75+
if (sent) {
76+
persistLog('✓ SUCCESS: Sent via sendBeacon', {
77+
url: trackingUrl,
78+
method: 'sendBeacon'
79+
});
80+
return;
81+
}
82+
}
83+
84+
// Fallback: try kilkaya API if available
85+
if (window.kilkaya && window.kilkaya.logger &&
86+
typeof window.kilkaya.logger.fireNow === 'function') {
87+
88+
var logData = window.kilkaya.pageData.getDefaultData();
89+
logData.cs = 1; // conversion
90+
window.kilkaya.logger.fireNow('pageView', logData, 'conversion');
91+
persistLog('✓ SUCCESS: Sent via Kilkaya API', {method: 'kilkaya.logger.fireNow'});
92+
return;
93+
}
94+
95+
} catch (err) {
96+
persistLog('✗ ERROR sending conversion', {error: err.message, stack: err.stack});
97+
}
98+
}, 150); // Small delay to ensure k5aMeta.conversion is set
99+
100+
} catch (e) {
101+
try {
102+
localStorage.setItem('k5a_send_log', JSON.stringify({
103+
timestamp: new Date().toISOString(),
104+
message: '✗ CRITICAL ERROR',
105+
data: {error: e.message, stack: e.stack}
106+
}));
107+
} catch (storageErr) {
108+
console.error('[K5A SEND] Error:', e);
109+
}
110+
}
111+
})(a, b);

tests/kilkaya/k5a_meta_conversion.test.js

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@ describe('k5a_meta_conversion', () => {
1212
// Save original utag if it exists
1313
originalUtag = window.utag;
1414

15-
// Mock utag
16-
window.utag = {
17-
data: {},
18-
cfg: {
19-
utDebug: true
20-
},
21-
DB: jest.fn()
22-
};
15+
// Mock console.error (since we removed utag.DB)
16+
jest.spyOn(console, 'error').mockImplementation();
2317

2418
// Clean up global variables
2519
delete global.a;
@@ -36,6 +30,7 @@ describe('k5a_meta_conversion', () => {
3630
}
3731
delete global.a;
3832
delete global.b;
33+
jest.restoreAllMocks();
3934
jest.resetModules();
4035
});
4136

@@ -53,7 +48,6 @@ describe('k5a_meta_conversion', () => {
5348
expect(window.k5aMeta.conversion).toBe(1);
5449
expect(Array.isArray(window.k5aMeta.cntTag)).toBe(true);
5550
expect(window.k5aMeta.cntTag).toContain('offer_12345');
56-
expect(window.utag.DB).toHaveBeenCalledWith('k5aMeta conversion set for checkout success');
5751
});
5852

5953
it('should not set conversion if event_name is not "checkout"', () => {
@@ -67,7 +61,6 @@ describe('k5a_meta_conversion', () => {
6761
require('../../extensions/kilkaya/k5a_meta_conversion.js');
6862

6963
expect(window.k5aMeta).toBeUndefined();
70-
expect(window.utag.DB).not.toHaveBeenCalledWith('k5aMeta conversion set for checkout success');
7164
});
7265

7366
it('should not set conversion if event_action is not "success"', () => {
@@ -81,7 +74,6 @@ describe('k5a_meta_conversion', () => {
8174
require('../../extensions/kilkaya/k5a_meta_conversion.js');
8275

8376
expect(window.k5aMeta).toBeUndefined();
84-
expect(window.utag.DB).not.toHaveBeenCalledWith('k5aMeta conversion set for checkout success');
8577
});
8678

8779
it('should initialize k5aMeta object if it does not exist', () => {
@@ -235,13 +227,16 @@ describe('k5a_meta_conversion', () => {
235227

236228
require('../../extensions/kilkaya/k5a_meta_conversion.js');
237229

238-
expect(window.utag.DB).toHaveBeenCalledWith(expect.stringContaining('k5aMeta conversion error:'));
230+
expect(console.error).toHaveBeenCalledWith(
231+
expect.stringContaining('[K5A CONVERSION] Error:'),
232+
expect.any(Error)
233+
);
239234

240235
// Clean up the read-only property
241236
delete window.k5aMeta;
242237
});
243238

244-
it('should handle missing utag gracefully', () => {
239+
it('should work without utag dependency', () => {
245240
global.a = 'some_value';
246241
global.b = {
247242
event_name: 'checkout',
@@ -250,9 +245,8 @@ describe('k5a_meta_conversion', () => {
250245
};
251246

252247
delete window.utag;
253-
global.utag = undefined;
254248

255-
// With the guard in place, the code should not throw even if utag is missing
249+
// Should work fine without utag
256250
expect(() => {
257251
require('../../extensions/kilkaya/k5a_meta_conversion.js');
258252
}).not.toThrow();
@@ -262,25 +256,6 @@ describe('k5a_meta_conversion', () => {
262256
expect(window.k5aMeta.conversion).toBe(1);
263257
expect(window.k5aMeta.cntTag).toContain('offer_12345');
264258
});
265-
it('should work when utag is defined but utag.data is missing', () => {
266-
global.a = 'some_value';
267-
global.b = {
268-
event_name: 'checkout',
269-
event_action: 'success',
270-
offer_id: '12345'
271-
};
272-
273-
window.utag = {
274-
DB: jest.fn()
275-
};
276-
// utag.data is undefined
277-
278-
require('../../extensions/kilkaya/k5a_meta_conversion.js');
279-
280-
expect(window.k5aMeta).toBeDefined();
281-
expect(window.k5aMeta.conversion).toBe(1);
282-
expect(window.k5aMeta.cntTag).toContain('offer_12345');
283-
});
284259

285260
it('should handle event_name and event_action type coercion', () => {
286261
global.a = 'some_value';
@@ -323,44 +298,4 @@ describe('k5a_meta_conversion', () => {
323298
expect(window.k5aMeta.cntTag).toContain('offer_special-offer_123@test');
324299
});
325300

326-
it('should not log when debug mode is disabled', () => {
327-
global.a = 'some_value';
328-
global.b = {
329-
event_name: 'checkout',
330-
event_action: 'success',
331-
offer_id: '12345'
332-
};
333-
334-
window.utag.cfg.utDebug = false;
335-
336-
require('../../extensions/kilkaya/k5a_meta_conversion.js');
337-
338-
expect(window.k5aMeta.conversion).toBe(1);
339-
expect(window.utag.DB).not.toHaveBeenCalled();
340-
});
341-
342-
it('should not log errors when debug mode is disabled', () => {
343-
global.a = 'some_value';
344-
global.b = {
345-
event_name: 'checkout',
346-
event_action: 'success',
347-
offer_id: '12345'
348-
};
349-
350-
window.utag.cfg.utDebug = false;
351-
352-
// Force an error
353-
Object.defineProperty(window, 'k5aMeta', {
354-
value: null,
355-
writable: false,
356-
configurable: true
357-
});
358-
359-
require('../../extensions/kilkaya/k5a_meta_conversion.js');
360-
361-
expect(window.utag.DB).not.toHaveBeenCalled();
362-
363-
// Clean up
364-
delete window.k5aMeta;
365-
});
366301
});

0 commit comments

Comments
 (0)