Skip to content

Commit 3ce385b

Browse files
Improve telemetry gathering for page context (#1962)
* Improve telemetry gathering for page context * Fix send event * Ignore blank content
1 parent 8c308c6 commit 3ce385b

File tree

1 file changed

+31
-24
lines changed

1 file changed

+31
-24
lines changed

injected/src/features/duck-ai-listener.js

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,8 @@ export default class DuckAiListener extends ContentFeature {
760760
if (pageDataParsed.content) {
761761
this.pageData = pageDataParsed;
762762

763+
this.promptTelemetry?.sendContextPixelInfo(pageDataParsed, DuckAiPromptTelemetry.CONTEXT_ATTACH_PIXEL_NAME);
764+
763765
// Resolve any pending context promise
764766
if (this.contextPromiseResolve) {
765767
this.contextPromiseResolve(true);
@@ -817,7 +819,6 @@ export default class DuckAiListener extends ContentFeature {
817819
const handleClick = this.handleSendMessage.bind(this);
818820

819821
sendButton.addEventListener('click', handleClick, true); // Capture phase
820-
// sendButton.addEventListener('click', handleClick, false); // Bubble phase
821822

822823
this.log.info('Set up message interception with multiple event listeners', sendButton);
823824
}
@@ -983,7 +984,7 @@ export default class DuckAiListener extends ContentFeature {
983984
this.mutationObserver = null;
984985

985986
// Callback function to execute when mutations are observed
986-
const callback = (_, observer) => {
987+
const callback = (/** @type {MutationRecord[]} */ _, observer) => {
987988
this.findTextBox();
988989
this.setupMessageInterception();
989990
if (this.textBox && this.pageData && this.sendButton && !this.hasContextBeenUsed) {
@@ -1011,13 +1012,17 @@ export default class DuckAiListener extends ContentFeature {
10111012
this.textBox = element;
10121013
this.log.info('Found AI text box');
10131014

1014-
// Add enter key handler to call handleSendMessage
1015-
element.addEventListener('keyup', (event) => {
1016-
if (event.key === 'Enter' && !event.shiftKey) {
1017-
this.log.info('Enter key pressed');
1018-
this.handleSendMessage();
1019-
}
1020-
});
1015+
// Add enter key handler using keydown with capture phase
1016+
element.addEventListener(
1017+
'keydown',
1018+
(event) => {
1019+
if (event.key === 'Enter' && !event.shiftKey) {
1020+
this.log.info('Enter key pressed');
1021+
this.handleSendMessage();
1022+
}
1023+
},
1024+
true,
1025+
);
10211026

10221027
// Set up property descriptor to intercept value reads for context appending
10231028
this.setupValuePropertyDescriptor(element);
@@ -1148,7 +1153,8 @@ ${truncatedWarning}
11481153
*/
11491154
class DuckAiPromptTelemetry {
11501155
static STORAGE_KEY = 'aiChatPageContextTelemetry';
1151-
static CONTEXT_PIXEL_NAME = 'dc_contextInfo';
1156+
static CONTEXT_ATTACH_PIXEL_NAME = 'dc_contextInfoOnAttach';
1157+
static CONTEXT_SEND_PIXEL_NAME = 'dc_contextInfoOnSubmit';
11521158
static DAILY_PIXEL_NAME = 'dc_pageContextDailyTelemetry';
11531159
static ONE_DAY_MS = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
11541160

@@ -1298,11 +1304,11 @@ class DuckAiPromptTelemetry {
12981304

12991305
const telemetryData = {
13001306
totalPrompts: String(totalPrompts),
1301-
avgRawPromptSize: this.bucketSizeByThousands(avgRawPromptSize),
1307+
avgRawPromptSize: this.bucketSize(avgRawPromptSize),
13021308
...createSizeFields('raw', rawSizeBuckets),
1303-
avgTotalPromptSize: this.bucketSizeByThousands(avgTotalPromptSize),
1309+
avgTotalPromptSize: this.bucketSize(avgTotalPromptSize),
13041310
...createSizeFields('total', totalSizeBuckets),
1305-
avgContextSize: this.bucketSizeByThousands(avgContextSize),
1311+
avgContextSize: this.bucketSize(avgContextSize),
13061312
contextUsageRate: String(Math.round(contextUsageRate * 100)),
13071313
};
13081314

@@ -1337,7 +1343,8 @@ class DuckAiPromptTelemetry {
13371343
if (!globalThis?.DDG?.pixel) {
13381344
return;
13391345
}
1340-
globalThis.DDG.pixel._pixels[DuckAiPromptTelemetry.CONTEXT_PIXEL_NAME] = {};
1346+
globalThis.DDG.pixel._pixels[DuckAiPromptTelemetry.CONTEXT_SEND_PIXEL_NAME] = {};
1347+
globalThis.DDG.pixel._pixels[DuckAiPromptTelemetry.CONTEXT_ATTACH_PIXEL_NAME] = {};
13411348
globalThis.DDG.pixel._pixels[DuckAiPromptTelemetry.DAILY_PIXEL_NAME] = {};
13421349
}
13431350

@@ -1354,30 +1361,30 @@ class DuckAiPromptTelemetry {
13541361
}
13551362

13561363
/**
1357-
* Bucket numbers by thousands for privacy-friendly reporting
1364+
* Bucket numbers by hundreds for privacy-friendly reporting
13581365
* @param {number} number - Number to bucket
1359-
* @returns {string} Bucket lower bound (e.g., '0', '1000', '2000')
1366+
* @returns {string} Bucket lower bound (e.g., '0', '100', '200')
13601367
*/
1361-
bucketSizeByThousands(number) {
1368+
bucketSize(number) {
13621369
if (number <= 0) {
13631370
return '0';
13641371
}
1365-
const bucketIndex = Math.floor(number / 1000);
1366-
return String(bucketIndex * 1000);
1372+
const bucketIndex = Math.floor(number / 100);
1373+
return String(bucketIndex * 100);
13671374
}
13681375

13691376
/**
13701377
* Send context pixel info when context is used
13711378
* @param {Object} contextData - Context data object
13721379
*/
1373-
sendContextPixelInfo(contextData) {
1374-
if (!contextData?.content) {
1380+
sendContextPixelInfo(contextData, pixelName) {
1381+
if (!contextData?.content || contextData.content.length === 0) {
13751382
this.log.warn('sendContextPixelInfo: No content available for pixel tracking');
13761383
return;
13771384
}
13781385

1379-
this.sendPixel(DuckAiPromptTelemetry.CONTEXT_PIXEL_NAME, {
1380-
contextLength: this.bucketSizeByThousands(contextData.content.length),
1386+
this.sendPixel(pixelName, {
1387+
contextLength: contextData.content.length,
13811388
});
13821389
}
13831390

@@ -1406,7 +1413,7 @@ class DuckAiPromptTelemetry {
14061413

14071414
// Send context pixel info if context was used
14081415
if (contextData && contextSize > 0) {
1409-
this.sendContextPixelInfo(contextData);
1416+
this.sendContextPixelInfo(contextData, DuckAiPromptTelemetry.CONTEXT_SEND_PIXEL_NAME);
14101417
}
14111418
// Check if we should fire daily telemetry
14121419
this.checkShouldFireDailyTelemetry();

0 commit comments

Comments
 (0)