Bug 1820707 - Record impressions and clicks for organic tiles. r=nanj
Currently, the Glean `newtab` ping and legacy scalars collect impressions and clicks for sponsored (Pocket and Contile) tiles, but not organic tiles from Places. This commit adds: * Support for recording organic impressions to the `TopSiteImpressionWrapper` component. * Support for recording organic clicks to the `TopSiteLink` component. * Instrumentation for recording organic impressions and clicks, separate from sponsored ones, to `TelemetryFeed`. Differential Revision: https://phabricator.services.mozilla.com/D171830
This commit is contained in:
@@ -72,7 +72,7 @@ export class ImpressionStats extends React.PureComponent {
|
||||
for (const card of cards) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.TOP_SITES_IMPRESSION_STATS,
|
||||
type: at.TOP_SITES_SPONSORED_IMPRESSION_STATS,
|
||||
data: {
|
||||
type: "impression",
|
||||
tile_id: card.id,
|
||||
|
||||
@@ -280,6 +280,58 @@ export class TopSiteLink extends React.PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
let impressionStats = null;
|
||||
if (link.type === SPOC_TYPE) {
|
||||
// Record impressions for Pocket tiles.
|
||||
impressionStats = (
|
||||
<ImpressionStats
|
||||
flightId={link.flightId}
|
||||
rows={[
|
||||
{
|
||||
id: link.id,
|
||||
pos: link.pos,
|
||||
shim: link.shim && link.shim.impression,
|
||||
advertiser: title.toLocaleLowerCase(),
|
||||
},
|
||||
]}
|
||||
dispatch={this.props.dispatch}
|
||||
source={TOP_SITES_SOURCE}
|
||||
/>
|
||||
);
|
||||
} else if (isSponsored(link)) {
|
||||
// Record impressions for non-Pocket sponsored tiles.
|
||||
impressionStats = (
|
||||
<TopSiteImpressionWrapper
|
||||
actionType={at.TOP_SITES_SPONSORED_IMPRESSION_STATS}
|
||||
tile={{
|
||||
position: this.props.index + 1,
|
||||
tile_id: link.sponsored_tile_id || -1,
|
||||
reporting_url: link.sponsored_impression_url,
|
||||
advertiser: title.toLocaleLowerCase(),
|
||||
source: NEWTAB_SOURCE,
|
||||
}}
|
||||
// For testing.
|
||||
IntersectionObserver={this.props.IntersectionObserver}
|
||||
document={this.props.document}
|
||||
dispatch={this.props.dispatch}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
// Record impressions for organic tiles.
|
||||
impressionStats = (
|
||||
<TopSiteImpressionWrapper
|
||||
actionType={at.TOP_SITES_ORGANIC_IMPRESSION_STATS}
|
||||
tile={{
|
||||
source: NEWTAB_SOURCE,
|
||||
}}
|
||||
// For testing.
|
||||
IntersectionObserver={this.props.IntersectionObserver}
|
||||
document={this.props.document}
|
||||
dispatch={this.props.dispatch}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
className={topSiteOuterClassName}
|
||||
@@ -342,34 +394,7 @@ export class TopSiteLink extends React.PureComponent {
|
||||
</div>
|
||||
</a>
|
||||
{children}
|
||||
{link.type === SPOC_TYPE ? (
|
||||
<ImpressionStats
|
||||
flightId={link.flightId}
|
||||
rows={[
|
||||
{
|
||||
id: link.id,
|
||||
pos: link.pos,
|
||||
shim: link.shim && link.shim.impression,
|
||||
advertiser: title.toLocaleLowerCase(),
|
||||
},
|
||||
]}
|
||||
dispatch={this.props.dispatch}
|
||||
source={TOP_SITES_SOURCE}
|
||||
/>
|
||||
) : null}
|
||||
{/* Set up an impression wrapper for the sponsored TopSite */}
|
||||
{link.sponsored_position ? (
|
||||
<TopSiteImpressionWrapper
|
||||
tile={{
|
||||
position: this.props.index + 1,
|
||||
tile_id: link.sponsored_tile_id || -1,
|
||||
reporting_url: link.sponsored_impression_url,
|
||||
advertiser: title.toLocaleLowerCase(),
|
||||
source: NEWTAB_SOURCE,
|
||||
}}
|
||||
dispatch={this.props.dispatch}
|
||||
/>
|
||||
) : null}
|
||||
{impressionStats}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
@@ -441,9 +466,8 @@ export class TopSite extends React.PureComponent {
|
||||
})
|
||||
);
|
||||
|
||||
// Fire off a spoc specific impression.
|
||||
if (this.props.link.type === SPOC_TYPE) {
|
||||
// Record a Pocket click.
|
||||
// Record a Pocket-specific click.
|
||||
this.props.dispatch(
|
||||
ac.ImpressionStats({
|
||||
source: TOP_SITES_SOURCE,
|
||||
@@ -458,11 +482,11 @@ export class TopSite extends React.PureComponent {
|
||||
})
|
||||
);
|
||||
|
||||
// Record a click for sponsored topsites.
|
||||
// Record a click for a Pocket sponsored tile.
|
||||
const title = this.props.link.label || this.props.link.hostname;
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.TOP_SITES_IMPRESSION_STATS,
|
||||
type: at.TOP_SITES_SPONSORED_IMPRESSION_STATS,
|
||||
data: {
|
||||
type: "click",
|
||||
position: this.props.link.pos + 1,
|
||||
@@ -472,23 +496,12 @@ export class TopSite extends React.PureComponent {
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
if (this.props.link.sendAttributionRequest) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.PARTNER_LINK_ATTRIBUTION,
|
||||
data: {
|
||||
targetURL: this.props.link.url,
|
||||
source: "newtab",
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
if (this.props.link.sponsored_position) {
|
||||
} else if (isSponsored(this.props.link)) {
|
||||
// Record a click for a non-Pocket sponsored tile.
|
||||
const title = this.props.link.label || this.props.link.hostname;
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.TOP_SITES_IMPRESSION_STATS,
|
||||
type: at.TOP_SITES_SPONSORED_IMPRESSION_STATS,
|
||||
data: {
|
||||
type: "click",
|
||||
position: this.props.index + 1,
|
||||
@@ -499,6 +512,29 @@ export class TopSite extends React.PureComponent {
|
||||
},
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// Record a click for an organic tile.
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.TOP_SITES_ORGANIC_IMPRESSION_STATS,
|
||||
data: {
|
||||
type: "click",
|
||||
source: NEWTAB_SOURCE,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.link.sendAttributionRequest) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.PARTNER_LINK_ATTRIBUTION,
|
||||
data: {
|
||||
targetURL: this.props.link.url,
|
||||
source: "newtab",
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.props.dispatch(
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import {
|
||||
actionCreators as ac,
|
||||
actionTypes as at,
|
||||
} from "common/Actions.sys.mjs";
|
||||
import { actionCreators as ac } from "common/Actions.sys.mjs";
|
||||
import React from "react";
|
||||
|
||||
const VISIBLE = "visible";
|
||||
@@ -27,11 +24,14 @@ export const INTERSECTION_RATIO = 0.5;
|
||||
*/
|
||||
export class TopSiteImpressionWrapper extends React.PureComponent {
|
||||
_dispatchImpressionStats() {
|
||||
const { tile } = this.props;
|
||||
const { actionType, tile } = this.props;
|
||||
if (!actionType) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.TOP_SITES_IMPRESSION_STATS,
|
||||
type: actionType,
|
||||
data: {
|
||||
type: "impression",
|
||||
...tile,
|
||||
@@ -144,5 +144,6 @@ export class TopSiteImpressionWrapper extends React.PureComponent {
|
||||
TopSiteImpressionWrapper.defaultProps = {
|
||||
IntersectionObserver: global.IntersectionObserver,
|
||||
document: global.document,
|
||||
actionType: null,
|
||||
tile: null,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user