Kameleoon Integration

Measure the first Ekoo audio play with a Kameleoon custom goal.

Recommended integration

Use the Ekoo played-0 event through data-ekoo-on-event. It confirms that playback started and does not depend on the widget's internal HTML structure.

1. Create the Goal in Kameleoon

  1. Open the relevant project in Kameleoon.
  2. Go to Settings > Goals, then create a custom goal such as Ekoo – Audio play.
  3. Copy the numeric goal ID.
  4. Attach the goal to the relevant experiments or personalizations.

2. Trigger the Conversion from Ekoo

Place this code before the widget script and replace only 123456 with your Kameleoon goal ID.

Ekoo callback to Kameleoon
javascript
1(() => {
2 const KAMELEOON_GOAL_ID = 123456; // Replace with your custom goal ID
3
4 window.onEkooEvent = function (data) {
5 if (data.stats.type !== 'played-0') return;
6
7 if (!window.Kameleoon?.API?.Goals?.processConversion) {
8 console.warn('[Ekoo] Kameleoon API is unavailable');
9 return;
10 }
11
12 window.Kameleoon.API.Goals.processConversion(KAMELEOON_GOAL_ID);
13 };
14})();

Then add this attribute to the element that initializes the Ekoo widget:

1data-ekoo-on-event="onEkooEvent"

3. Verify the Integration

In the browser console, confirm that the Kameleoon conversion API is available:

1typeof window.Kameleoon?.API?.Goals?.processConversion
2// Expected result: "function"

The expected result is "function". Then use Kameleoon Preview mode, start playback once, and check the conversion on the goal.

Temporary Workaround Without the Ekoo Callback

Kameleoon tracking based only on a CSS selector can miss clicks: the Play button is inside the widget's Shadow DOM and stops event propagation. If you cannot add data-ekoo-on-event yet, temporarily use a capture-phase listener:

Temporary DOM capture fallback
javascript
1(() => {
2 const KAMELEOON_GOAL_ID = 123456; // Replace with your custom goal ID
3
4 if (window.__ekooKameleoonTrackingInstalled) return;
5 window.__ekooKameleoonTrackingInstalled = true;
6
7 const trackedWidgets = new WeakSet();
8
9 function trackPlay(event) {
10 const path = event.composedPath?.() || [];
11 const isPlayButton = path.some((element) =>
12 element?.matches?.('.ekoo-widget-container-picture-button')
13 );
14
15 if (!isPlayButton) return;
16
17 const widget = path.find((element) => element?.tagName === 'EKOO-WIDGET');
18
19 if (!widget || widget.classList.contains('playing') || trackedWidgets.has(widget)) {
20 return;
21 }
22
23 if (!window.Kameleoon?.API?.Goals?.processConversion) {
24 console.warn('[Ekoo] Kameleoon API is unavailable');
25 return;
26 }
27
28 trackedWidgets.add(widget);
29 window.Kameleoon.API.Goals.processConversion(KAMELEOON_GOAL_ID);
30 }
31
32 document.addEventListener('pointerdown', trackPlay, true);
33 document.addEventListener('keydown', (event) => {
34 if (event.key === 'Enter' || event.key === ' ') trackPlay(event);
35 }, true);
36})();
⚠️

Fallback limitation

This method measures the intent to click Play, not confirmation that audio playback started. Replace it with the native callback when possible.

Expected Behavior

  • One conversion on the first audio play.
  • No additional conversion on pause or resume.
  • A new widget can trigger its own conversion.

To also send events to GTM or GA4, see the DataLayer guide.

Kameleoon — Documentation — Ekoo