Skip to content

Commit

Permalink
Merge pull request #12075 from bbc/nasaa-amp-experiment-analytics
Browse files Browse the repository at this point in the history
[NASAA-205] - Send top stories experiment analytics events
  • Loading branch information
karinathomasbbc authored Nov 18, 2024
2 parents 9b3b30f + b20dc97 commit c428e3b
Show file tree
Hide file tree
Showing 19 changed files with 1,041 additions and 122 deletions.
4 changes: 2 additions & 2 deletions scripts/bundleSize/bundleSizeConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
* We are allowing a variance of -5 on `MIN_SIZE` and +5 on `MAX_SIZE` to avoid the need for frequent changes, as bundle sizes can fluctuate
*/

export const MIN_SIZE = 635 - 5;
export const MAX_SIZE = 1175 + 5;
export const MIN_SIZE = 644 - 5;
export const MAX_SIZE = 1183 + 5;
53 changes: 52 additions & 1 deletion src/app/components/ATIAnalytics/atiUrl/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ describe('getThingAttributes', () => {
timePublished: 'timePublished',
timeUpdated: 'timeUpdated',
}} | ${'https://www.bbcnewsd73hkzno2ini43t4gblxvycyac5aw4gnv7t2rccijh7745uqd.onion/news'} | ${['s2=producerId', 'p=pageIdentifier', 'x1=[contentId]', 'x3=[appName]', 'x4=[language]', 'x7=[contentType]', 'x11=[timePublished]', 'x12=[timeUpdated]', 'x13=[ldpThingLabels]', 'x14=[ldpThingIds]', 'xto=SEC------', 'product_platform=tor-bbc']}
${{
appName: 'appName',
contentId: 'contentId',
contentType: 'contentType',
language: 'language',
ldpThingIds: 'ldpThingIds',
ldpThingLabels: 'ldpThingLabels',
pageIdentifier: 'pageIdentifier',
pageTitle: 'pageTitle',
platform: 'platform',
producerId: 'producerId',
timePublished: 'timePublished',
timeUpdated: 'timeUpdated',
ampExperimentName: 'someExperiment',
}} | ${'https://www.bbc.com/news'} | ${['s2=producerId', 'p=pageIdentifier', 'x1=[contentId]', 'x3=[appName]', 'x4=[language]', 'x7=[contentType]', 'x11=[timePublished]', 'x12=[timeUpdated]', 'x13=[ldpThingLabels]', 'x14=[ldpThingIds]', 'xto=SEC------', 'mv_test=Google Discover', 'mv_experiment_id=someExperiment', 'mv_creation=VARIANT(someExperiment)']}
`(
'should take in optional props and add them as correct query params',
({ props, currentUrl, expectedValues }) => {
Expand Down Expand Up @@ -244,6 +259,39 @@ describe('buildATIEventTrackUrl', () => {
format: 'format',
url: 'url',
detailedPlacement: 'detailedPlacement',
experimentVariant: 'variant_1',
});

expect(splitUrl(atiEventTrackUrl)).toEqual([
'http://foobar.com',
'idclient=getAtUserId',
's=getDestination',
'p=pageIdentifier',
'r=getScreenInfo',
're=getBrowserViewPort',
'hl=getCurrentTime',
'lng=getDeviceLanguage',
'atc=PUB-[campaignID]-[component]-[variant_1]-[format]-[pageIdentifier]-[detailedPlacement]-[]-[url]',
'type=AT',
]);
});

it('should return the correct url with mvt properties if ampExperimentName is present', () => {
process.env.SIMORGH_ATI_BASE_URL = 'http://foobar.com?';

const atiEventTrackUrl = buildATIEventTrackUrl({
pageIdentifier: 'pageIdentifier',
service: 'news',
platform: 'canonical',
statsDestination: 'statsDestination',
componentName: 'component',
type: 'type',
campaignID: 'campaignID',
format: 'format',
url: 'url',
detailedPlacement: 'detailedPlacement',
experimentVariant: 'variant_1',
ampExperimentName: 'someExperiment',
});

expect(splitUrl(atiEventTrackUrl)).toEqual([
Expand All @@ -255,7 +303,10 @@ describe('buildATIEventTrackUrl', () => {
're=getBrowserViewPort',
'hl=getCurrentTime',
'lng=getDeviceLanguage',
'atc=PUB-[campaignID]-[component]-[]-[format]-[pageIdentifier]-[detailedPlacement]-[]-[url]',
'atc=PUB-[campaignID]-[component]-[variant_1]-[format]-[pageIdentifier]-[detailedPlacement]-[]-[url]',
'mv_test=Google Discover',
'mv_experiment_id=someExperiment',
'mv_creation=variant_1',
'type=AT',
]);
});
Expand Down
54 changes: 54 additions & 0 deletions src/app/components/ATIAnalytics/atiUrl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const buildATIPageTrackPath = ({
categoryName,
campaigns,
nationsProducer,
ampExperimentName,
}: ATIPageTrackingProps) => {
const href = getHref(platform);
const referrer = getReferrer(platform, origin, previousPath);
Expand Down Expand Up @@ -214,6 +215,31 @@ export const buildATIPageTrackPath = ({
value: getATIMarketingString(href, campaignType),
wrap: false,
},
...(ampExperimentName
? [
{
key: 'mv_test',
description: 'AMP experiment project name',
value: `Google Discover`,
wrap: false,
disableEncoding: true,
},
{
key: 'mv_experiment_id',
description: 'AMP experiment name',
value: `${ampExperimentName}`,
wrap: false,
disableEncoding: true,
},
{
key: 'mv_creation',
description: 'AMP experiment variant name',
value: `VARIANT(${ampExperimentName})`,
wrap: false,
disableEncoding: true,
},
]
: []),
...getRSSMarketingString(href, campaignType),
...(onOnionTld()
? [
Expand Down Expand Up @@ -252,6 +278,8 @@ export const buildATIEventTrackUrl = ({
advertiserID,
url,
detailedPlacement,
experimentVariant,
ampExperimentName,
}: ATIEventTrackingProps) => {
// on AMP, variable substitutions are used in the value and they cannot be
// encoded: https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md
Expand Down Expand Up @@ -323,10 +351,36 @@ export const buildATIEventTrackUrl = ({
advertiserID,
url,
detailedPlacement,
experimentVariant,
}),
wrap: false,
disableEncoding: true,
},
...(ampExperimentName
? [
{
key: 'mv_test',
description: 'AMP experiment project name',
value: `Google Discover`,
wrap: false,
disableEncoding: true,
},
{
key: 'mv_experiment_id',
description: 'AMP experiment name',
value: `${ampExperimentName}`,
wrap: false,
disableEncoding: true,
},
{
key: 'mv_creation',
description: 'AMP experiment variant name',
value: `${experimentVariant}`,
wrap: false,
disableEncoding: true,
},
]
: []),
];

return `${getEnvConfig().SIMORGH_ATI_BASE_URL}${getAtiUrl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,27 @@ describe('implementation of buildPageATIParams and buildPageATIUrl', () => {

expect(parsedATIURLParams).toEqual(expectedATIURLParams);
});

it('should return ampExperimentName only if it is present in atiData', () => {
const result = buildPageATIParams({
atiData: {
...articlePageAtiData,
ampExperimentName: 'topStoriesExperiment',
},
requestContext: {
...requestContext,
isUK: false,
origin: 'example.com',
pageType: 'article',
previousPath: 'previousPath',
},
serviceContext: { ...serviceContext, service: 'burmese', lang: 'my' },
});
expect(result).toEqual({
...validPageURLParams,
ampExperimentName: 'topStoriesExperiment',
});
});
});

describe('Media Article Page', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const buildPageATIParams = ({
producerId,
timePublished,
timeUpdated,
ampExperimentName,
} = atiData;

return {
Expand All @@ -49,6 +50,7 @@ export const buildPageATIParams = ({
statsDestination,
timePublished,
timeUpdated,
...(ampExperimentName && { ampExperimentName }),
};
};

Expand Down
4 changes: 4 additions & 0 deletions src/app/components/ATIAnalytics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface ATIData {
producerName?: string | null;
timePublished?: string | null;
timeUpdated?: string | null;
ampExperimentName?: string;
}

export interface PageData {
Expand Down Expand Up @@ -109,6 +110,8 @@ export interface ATIEventTrackingProps {
advertiserID?: string;
url?: string;
detailedPlacement?: string;
experimentVariant?: string;
ampExperimentName?: string;
}

export interface ATIPageTrackingProps {
Expand All @@ -131,6 +134,7 @@ export interface ATIPageTrackingProps {
categoryName?: string | null;
campaigns?: { campaignId?: string; campaignName?: string }[] | null;
nationsProducer?: string | null;
ampExperimentName?: string;
}

export interface ATIProps {
Expand Down
46 changes: 45 additions & 1 deletion src/app/components/AmpExperiment/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,22 @@ const multipleExperimentConfig = {
},
};

const analyticsConfig = {
requests: {
base: 'somehost.com',
clicks: 'somehost.com?somequeryparam=somevalue',
},
triggers: {
trackClicks: {
on: 'click',
request: 'clicks',
selector: 'a',
},
},
};

describe('Amp experiment container on Amp pages', () => {
it('should render an amp-experiment with the expected config', async () => {
it('should render an amp-experiment with the expected experiment config', async () => {
const { container } = render(
<AmpExperiment experimentConfig={experimentConfig} />,
);
Expand Down Expand Up @@ -66,6 +80,36 @@ describe('Amp experiment container on Amp pages', () => {
`);
});

it('should render an amp-analytics with the expected analytics config if present', async () => {
const { container } = render(
<AmpExperiment
experimentConfig={experimentConfig}
analyticsConfig={analyticsConfig}
/>,
);
expect(container.querySelector('amp-experiment')).toBeInTheDocument();
expect(container).toMatchInlineSnapshot(`
<div>
<amp-experiment>
<script
type="application/json"
>
{"someExperiment":{"variants":{"control":33,"variant_1":33,"variant_2":33}}}
</script>
</amp-experiment>
<amp-analytics
type="piano"
>
<script
type="application/json"
>
{"requests":{"base":"somehost.com","clicks":"somehost.com?somequeryparam=somevalue"},"triggers":{"trackClicks":{"on":"click","request":"clicks","selector":"a"}}}
</script>
</amp-analytics>
</div>
`);
});

it(`should add amp-experiment extension script to page head`, async () => {
render(<AmpExperiment experimentConfig={experimentConfig} />);

Expand Down
49 changes: 42 additions & 7 deletions src/app/components/AmpExperiment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,31 @@ type AmpExperimentConfig = {
};
};

type AmpAnalyticsConfig = {
requests: Record<string, string>;
triggers: Record<
string,
{
on: string;
request: string;
selector?: string;
visibilitySpec?: {
selector?: string;
visiblePercentageMin?: number;
totalTimeMin?: number;
continuousTimeMin?: number;
};
}
>;
};

type AmpExperimentProps = {
[key: Experiment]: AmpExperimentConfig;
experimentConfig: AmpExperimentConfig;
analyticsConfig?: AmpAnalyticsConfig;
};

type AmpScriptProps = AmpExperimentConfig | AmpAnalyticsConfig;

const AmpHead = () => (
<Helmet>
<script
Expand All @@ -32,17 +53,31 @@ const AmpHead = () => (
</Helmet>
);

const AmpExperiment = ({ experimentConfig }: AmpExperimentProps) => {
const AmpScript = ({ config }: { config: AmpScriptProps }) => {
return (
<script
type="application/json"
/* eslint-disable-next-line react/no-danger */
dangerouslySetInnerHTML={{ __html: JSON.stringify(config) }}
/>
);
};

const AmpExperiment = ({
experimentConfig,
analyticsConfig,
}: AmpExperimentProps) => {
return (
<>
<AmpHead />
<amp-experiment>
<script
type="application/json"
/* eslint-disable-next-line react/no-danger */
dangerouslySetInnerHTML={{ __html: JSON.stringify(experimentConfig) }}
/>
<AmpScript config={experimentConfig} />
</amp-experiment>
{analyticsConfig && (
<amp-analytics type="piano">
<AmpScript config={analyticsConfig} />
</amp-analytics>
)}
</>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/lib/analyticsUtils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export const getEventInfo = ({
pageIdentifier = '',
componentName = '',
campaignID = '',
variant = '', // not a service variant - used for A/B testing
experimentVariant = '',
format = '',
detailedPlacement = '',
advertiserID = '',
Expand All @@ -280,7 +280,7 @@ export const getEventInfo = ({
const generalPlacement = pageIdentifier;
const creation = componentName;

return `PUB-[${campaignID}]-[${creation}]-[${variant}]-[${format}]-[${generalPlacement}]-[${detailedPlacement}]-[${advertiserID}]-[${url}]`;
return `PUB-[${campaignID}]-[${creation}]-[${experimentVariant}]-[${format}]-[${generalPlacement}]-[${detailedPlacement}]-[${advertiserID}]-[${url}]`;
};

export const getThingAttributes = (attribute, articleData) => {
Expand Down
2 changes: 1 addition & 1 deletion src/app/lib/analyticsUtils/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ describe('getEventInfo', () => {
format: 'format',
detailedPlacement: 'detailed-placement',
advertiserID: 'mundo',
variant: 'a/b-test',
experimentVariant: 'a/b-test',
};

it('should return url section', () => {
Expand Down
Loading

0 comments on commit c428e3b

Please sign in to comment.