From 663461df255f0a17f91cba26626e3d0654fb4f18 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Fri, 10 May 2024 08:34:18 +0100 Subject: [PATCH] Add element --- README.md | 8 ++++++++ src/attribution/onINP.ts | 8 +++++--- src/types/inp.ts | 8 ++++++++ test/e2e/onINP-test.js | 7 ++++--- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2119358c..521895a2 100644 --- a/README.md +++ b/README.md @@ -902,6 +902,14 @@ interface INPAttribution { */ interactionTarget: string; + /** + * A node identifying the element that the user first interacted with + * as part of the frame where the INP candidate interaction occurred. + * If `interactionTargetElement` is null, that generally means the + * element was removed from the DOM after the interaction. + */ + interactionTargetElement?: Node; + /** * The time when the user first interacted during the frame where the INP * candidate interaction occurred (if more than one interaction occurred diff --git a/src/attribution/onINP.ts b/src/attribution/onINP.ts index 1521e53b..3481a442 100644 --- a/src/attribution/onINP.ts +++ b/src/attribution/onINP.ts @@ -236,9 +236,10 @@ const attributeINP = (metric: INPMetric): INPMetricWithAttribution => { // https://bugs.chromium.org/p/chromium/issues/detail?id=1367329 // We also fallback to interactionTargetMap for when target removed from DOM const firstEntryWithTarget = metric.entries.find((entry) => entry.target); - const interactionTarget = firstEntryWithTarget - ? getSelector(firstEntryWithTarget.target) - : getSelector(interactionTargetMap.get(firstEntry.interactionId)) || ''; + const interactionTargetElement = + firstEntryWithTarget?.target || + interactionTargetMap.get(firstEntry.interactionId); + const interactionTarget = getSelector(interactionTargetElement); // Since entry durations are rounded to the nearest 8ms, we need to clamp // the `nextPaintTime` value to be higher than the `processingEnd` or @@ -254,6 +255,7 @@ const attributeINP = (metric: INPMetric): INPMetricWithAttribution => { const attribution: INPAttribution = { interactionTarget: interactionTarget, + interactionTargetElement: interactionTargetElement, interactionType: firstEntry.name.startsWith('key') ? 'keyboard' : 'pointer', interactionTime: firstEntry.startTime, nextPaintTime: nextPaintTime, diff --git a/src/types/inp.ts b/src/types/inp.ts index d469be47..577b998e 100644 --- a/src/types/inp.ts +++ b/src/types/inp.ts @@ -38,6 +38,14 @@ export interface INPAttribution { */ interactionTarget: string; + /** + * A node identifying the element that the user first interacted with + * as part of the frame where the INP candidate interaction occurred. + * If `interactionTargetElement` is null, that generally means the + * element was removed from the DOM after the interaction. + */ + interactionTargetElement?: Node; + /** * The time when the user first interacted during the frame where the INP * candidate interaction occurred (if more than one interaction occurred diff --git a/test/e2e/onINP-test.js b/test/e2e/onINP-test.js index f7bb9d3a..2bbc90f0 100644 --- a/test/e2e/onINP-test.js +++ b/test/e2e/onINP-test.js @@ -668,10 +668,11 @@ describe('onINP()', async function () { await stubVisibilityChange('hidden'); await beaconCountIs(1); - const [inp1] = await getBeacons(); + const [inp] = await getBeacons(); - assert.equal(inp1.attribution.interactionType, 'pointer'); - assert.equal(inp1.attribution.interactionTarget, '#reset'); + assert.equal(inp.attribution.interactionType, 'pointer'); + assert.equal(inp.attribution.interactionTarget, '#reset'); + assert(inp.attribution.interactionTargetElement); }); it('includes LoAF entries if the browser supports it', async function () {