Bug 1816730 - Step 2: Allow targets in content process to register click events - r=Standard8

Differential Revision: https://phabricator.services.mozilla.com/D175311
This commit is contained in:
James Teow
2023-04-21 16:54:22 +00:00
parent 83116d3c19
commit 1e0f3a44da
6 changed files with 239 additions and 0 deletions

View File

@@ -46,6 +46,7 @@ export var SearchSERPTelemetryUtils = {
AD_LINK: "ad_link",
AD_SIDEBAR: "ad_sidebar",
AD_SITELINK: "ad_sitelink",
INCONTENT_SEARCHBOX: "incontent_searchbox",
NON_ADS_LINK: "non_ads_link",
REFINED_SEARCH_BUTTONS: "refined_search_buttons",
SHOPPING_TAB: "shopping_tab",
@@ -270,6 +271,10 @@ class TelemetryHandler {
this._contentHandler._searchProviderInfo = this._searchProviderInfo;
}
reportPageAction(info, browser) {
this._contentHandler._reportPageAction(info, browser);
}
reportPageWithAds(info, browser) {
this._contentHandler._reportPageWithAds(info, browser);
}
@@ -1066,6 +1071,49 @@ class ContentHandler {
telemetryState.adImpressionsReported = true;
}
}
/**
* Records a page action from a SERP page. Normally, actions are tracked in
* parent process by observing network events but some actions are not
* possible to detect outside of subscribing to the child process.
*
* @param {object} info
* The search provider infomation for the page.
* @param {string} info.type
* The component type that was clicked on.
* @param {string} info.action
* The action taken on the page.
* @param {object} browser
* The browser associated with the page.
*/
_reportPageAction(info, browser) {
let item = this._findBrowserItemForURL(info.url);
if (!item) {
return;
}
let impressionId = item.browserTelemetryStateMap.get(browser)?.impressionId;
if (info.type && impressionId) {
lazy.logConsole.debug(`Recorded page action:`, {
impressionId,
type: info.type,
action: info.action,
});
Glean.serp.engagement.record({
impression_id: impressionId,
action: info.action,
target: info.type,
});
impressionIdsWithoutEngagementsSet.delete(impressionId);
} else {
lazy.logConsole.warn(
"Expected to report a",
info.action,
"engagement for",
info.url,
"but couldn't find an impression id."
);
}
}
}
export var SearchSERPTelemetry = new TelemetryHandler();

View File

@@ -73,6 +73,7 @@ support-files =
searchTelemetryAd_components_text.html
searchTelemetryAd_nonAdsLink_redirect.html
searchTelemetryAd_nonAdsLink_redirect.html^headers^
searchTelemetryAd_searchbox.html
serp.css
[browser_search_telemetry_searchbar.js]
https_first_disabled = true

View File

@@ -48,6 +48,16 @@ const TEST_PROVIDER_INFO = [
},
},
},
{
type: SearchSERPTelemetryUtils.COMPONENTS.INCONTENT_SEARCHBOX,
included: {
parent: {
selector: "form input",
},
},
topDown: true,
nonAd: true,
},
{
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
included: {
@@ -329,3 +339,36 @@ add_task(async function test_click_non_ads_link() {
BrowserTestUtils.removeTab(tab);
});
// Search box is a special case which has to be tracked in the child process.
add_task(async function test_click_incontent_searchbox() {
resetTelemetry();
let url = getSERPUrl("searchTelemetryAd_searchbox.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseImpressionReceived();
// Click on the searchbox.
await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
content.document.querySelector("form input").click();
});
assertImpressionEvents([
{
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
source: "unknown",
},
engagements: [
{
action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
target: SearchSERPTelemetryUtils.COMPONENTS.INCONTENT_SEARCHBOX,
},
],
},
]);
BrowserTestUtils.removeTab(tab);
});

View File

@@ -0,0 +1,68 @@
<!-- This HTML file encodes the ad link in the data attribute -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="./serp.css" />
</head>
<body>
<section>
<form role="search">
<input type="text" />
</form>
</section>
<!-- TODO: Remove links with ads once page checks can be done without any ads -->
<section id="searchresults">
<div class="lhs">
<div class="moz_ad">
<h5 test-label>ad_sitelink</h5>
<a href="https://example.com/ad">
<h2>Example Result</h2>
</a>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras ac velit sed tellus facilisis euismod.</p>
<span><a href="https://example.com/ad">Ad link that says there are 10 Locations nearby</a></span>
<div class="multi-col">
<div>
<a href="https://example.com/ad">
<h2>New Releases</h2>
</a>
<span>Cras ac velit sed tellus</span>
</div>
<div>
<a href="https://example.com/ad">
<h2>Men's</h2>
</a>
<span>Cras ac velit sed tellus</span>
</div>
<div>
<a href="https://example.com/ad">
<h2>Women's</h2>
</a>
<span>Cras ac velit sed tellus</span>
</div>
<div>
<!-- Ensure ads encoded in data-attributes are also recorded properly -->
<a data-moz-attr="https://example.com/ad" href="https://example.com/normal-link">
<h2>Sale</h2>
</a>
<span>Cras ac velit sed tellus</span>
</div>
</div>
</div>
</div>
<div class="rhs">
<h5 test-label>ad_sidebar</h5>
<div class="moz_ad">
<a href="https://example.com/ad">
<div class="mock-image">Mock ad image</div>
</a>
<a href="https://example.com/ad">
<h3>Buy Example Now</h3>
</a>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
<a href="https://example.com/ad">Buy Now</a>
</div>
</div>
</section>
</body>
</html>