Skip to content
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/audits/gpt-bids-parallel.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {getCriticalGraph} = require('../utils/graph');
const {getTimingsByRecord} = require('../utils/network-timing');
const {isImplTag, isBidRequest, getAbbreviatedUrl, getHeaderBidder} = require('../utils/resource-classification');
const {isGptImplTag, isBidRequest, getAbbreviatedUrl, getHeaderBidder} = require('../utils/resource-classification');

/** @typedef {LH.Artifacts.NetworkRequest} NetworkRequest */
/** @typedef {LH.Gatherer.Simulation.NodeTiming} NodeTiming */
Expand Down Expand Up @@ -73,7 +73,7 @@ class GptBidsInParallel extends Audit {
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const network = await NetworkRecords.request(devtoolsLog, context);

const pubadsImpl = network.find((r) => isImplTag(r.url));
const pubadsImpl = network.find((r) => isGptImplTag(r.url));
if (!pubadsImpl) {
return auditNotApplicable.NoTag;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,41 @@ const NetworkRecords = require('lighthouse/lighthouse-core/computed/network-reco
const util = require('util');
const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {isGptTag} = require('../utils/resource-classification');
const {isAdTag} = require('../utils/resource-classification');
const {URL} = require('url');

const UIStrings = {
title: 'GPT tag is loaded over HTTPS',
failureTitle: 'Load GPT over HTTPS',
description: 'For privacy and security, always load GPT over HTTPS. ' +
'Insecure pages should explicitly request the GPT script securely. Example:' +
'`<script async src=\"https://securepubads.g.doubleclick.net/tag/js/gpt.js\"' +
'>`. [Learn more](' +
'https://developers.google.com/publisher-ads-audits/reference/audits/loads-gpt-over-https' +
title: 'Ad tag is loaded over HTTPS',
failureTitle: 'Load ad tag over HTTPS',
description: 'For privacy and security, always load GPT/AdSense over ' +
'HTTPS. Insecure pages should explicitly request the ad script securely. ' +
'Examples: ' +
'`<script async ' +
'src=\"https://securepubads.g.doubleclick.net/tag/js/gpt.js\">` or ' +
'`<script async ' +
'src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\">`' +
'. [Learn more](' +
'https://developers.google.com/publisher-ads-audits/reference/audits/loads-ad-tag-over-https' +
').',
failureDisplayValue: 'Load gpt.js over HTTPS',
failureDisplayValue: 'Load ad tag over HTTPS',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);


/**
* Simple audit that checks if gpt is loaded over https.
* Simple audit that checks if GPT/AdSense is loaded over https.
* Currently based on network logs since it covers statically and dynamically
* loaded scripts from the main page and iframes.
*/
class LoadsGptOverHttps extends Audit {
class LoadsAdTagOverHttps extends Audit {
/**
* @return {LH.Audit.Meta}
* @override
*/
static get meta() {
return {
id: 'loads-gpt-over-https',
id: 'loads-ad-tag-over-https',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
Expand All @@ -69,35 +73,35 @@ class LoadsGptOverHttps extends Audit {
return auditNotApplicable.NoRecords;
}

const gptRequests = networkRecords
.filter((record) => isGptTag(new URL(record.url)));
const adRequests = networkRecords
.filter((record) => isAdTag(new URL(record.url)));

const secureGptRequests = gptRequests.filter((request) => request.isSecure);
const secureAdRequests = adRequests.filter((request) => request.isSecure);

/** @type {LH.Audit.Details.DebugData} */
const details = {
type: 'debugdata',
numGptHttpReqs: gptRequests.length - secureGptRequests.length,
numGptHttpsReqs: secureGptRequests.length,
numAdTagHttpReqs: adRequests.length - secureAdRequests.length,
numAdTagHttpsReqs: secureAdRequests.length,
};

if (!gptRequests.length) {
const returnVal = auditNotApplicable.NoGpt;
if (!adRequests.length) {
const returnVal = auditNotApplicable.NoTag;
returnVal.details = details;
return returnVal;
}

return {
numericValue: details.numGptHttpReqs,
score: details.numGptHttpReqs ? 0 : 1,
displayValue: details.numGptHttpReqs ?
numericValue: details.numAdTagHttpReqs,
score: details.numAdTagHttpReqs ? 0 : 1,
displayValue: details.numAdTagHttpReqs ?
util.format(
str_(UIStrings.failureDisplayValue), details.numGptHttpReqs) :
str_(UIStrings.failureDisplayValue), details.numAdTagHttpReqs) :
'',
details,
};
}
}

module.exports = LoadsGptOverHttps;
module.exports = LoadsAdTagOverHttps;
module.exports.UIStrings = UIStrings;
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class LoadsGptFromSgdn extends Audit {
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
const gptUrl = networkRecords.map((r) => new URL(r.url)).find(isGptTag);
if (!gptUrl) {
return auditNotApplicable.NoGpt;
return auditNotApplicable.NoTag;
}
return {
score: Number(gptUrl.host === 'securepubads.g.doubleclick.net'),
Expand Down
2 changes: 0 additions & 2 deletions lighthouse-plugin-publisher-ads/messages/common-strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const UIStrings = {
NOT_APPLICABLE__NO_ADS: 'No ads requested',
NOT_APPLICABLE__NO_BIDS: 'No bids detected',
NOT_APPLICABLE__NO_EVENT_MATCHING_REQ: 'No event matches network records',
NOT_APPLICABLE__NO_GPT: 'GPT not requested',
NOT_APPLICABLE__NO_RECORDS: 'No successful network records',
NOT_APPLICABLE__NO_VISIBLE_SLOTS: 'No visible slots',
NOT_APPLICABLE__NO_TAG: 'No tag requested',
Expand Down Expand Up @@ -69,7 +68,6 @@ const auditNotApplicable = {
NoBids: notApplicableObj(UIStrings.NOT_APPLICABLE__NO_BIDS),
NoEventMatchingReq: notApplicableObj(
UIStrings.NOT_APPLICABLE__NO_EVENT_MATCHING_REQ),
NoGpt: notApplicableObj(UIStrings.NOT_APPLICABLE__NO_GPT),
NoRecords: notApplicableObj(UIStrings.NOT_APPLICABLE__NO_RECORDS),
NoVisibleSlots: notApplicableObj(UIStrings.NOT_APPLICABLE__NO_VISIBLE_SLOTS),
NoTag: notApplicableObj(UIStrings.NOT_APPLICABLE__NO_TAG),
Expand Down
20 changes: 8 additions & 12 deletions lighthouse-plugin-publisher-ads/messages/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -299,20 +299,20 @@
"message": "GPT tag is loaded from recommended host",
"description": ""
},
"audits/loads-gpt-over-https.js | description": {
"message": "For privacy and security, always load GPT over HTTPS. Insecure pages should explicitly request the GPT script securely. Example:`<script async src=\"https://securepubads.g.doubleclick.net/tag/js/gpt.js\">`. [Learn more](https://developers.google.com/publisher-ads-audits/reference/audits/loads-gpt-over-https).",
"audits/loads-ad-tag-over-https.js | description": {
"message": "For privacy and security, always load GPT/AdSense over HTTPS. Insecure pages should explicitly request the ad script securely. Example:`<script async src=\"https://securepubads.g.doubleclick.net/tag/js/gpt.js\">` or `<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\">`. [Learn more](https://developers.google.com/publisher-ads-audits/reference/audits/loads-ad-tag-over-https).",
"description": ""
},
"audits/loads-gpt-over-https.js | failureDisplayValue": {
"message": "Load gpt.js over HTTPS",
"audits/loads-ad-tag-over-https.js | failureDisplayValue": {
"message": "Load ad tag over HTTPS",
"description": ""
},
"audits/loads-gpt-over-https.js | failureTitle": {
"message": "Load GPT over HTTPS",
"audits/loads-ad-tag-over-https.js | failureTitle": {
"message": "Load ad tag over HTTPS",
"description": ""
},
"audits/loads-gpt-over-https.js | title": {
"message": "GPT tag is loaded over HTTPS",
"audits/loads-ad-tag-over-https.js | title": {
"message": "Ad tag is loaded over HTTPS",
"description": ""
},
"audits/script-injected-tags.js | columnDuration": {
Expand Down Expand Up @@ -483,10 +483,6 @@
"message": "No event matches network records",
"description": ""
},
"messages/common-strings.js | NOT_APPLICABLE__NO_GPT": {
"message": "GPT not requested",
"description": ""
},
"messages/common-strings.js | NOT_APPLICABLE__NO_RECORDS": {
"message": "No successful network records",
"description": ""
Expand Down
13 changes: 5 additions & 8 deletions lighthouse-plugin-publisher-ads/messages/locales/en-XL.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,16 @@
"audits/loads-gpt-from-sgdn.js | title": {
"message": "ĜṔT̂ t́âǵ îś l̂óâd́êd́ f̂ŕôḿ r̂éĉóm̂ḿêńd̂éd̂ h́ôśt̂"
},
"audits/loads-gpt-over-https.js | description": {
"message": "F̂ór̂ ṕr̂ív̂áĉý âńd̂ śêćûŕît́ŷ, ál̂ẃâýŝ ĺôád̂ ǴP̂T́ ôv́êŕ ĤT́T̂ṔŜ. Ín̂śêćûŕê ṕâǵêś ŝh́ôúl̂d́ êx́p̂ĺîćît́l̂ý r̂éq̂úêśt̂ t́ĥé ĜṔT̂ śĉŕîṕt̂ śêćûŕêĺŷ. Éx̂ám̂ṕl̂é:`<ŝćr̂íp̂t́ âśŷńĉ śr̂ć=\"ĥt́t̂ṕŝ://śêćûŕêṕûb́âd́ŝ.ǵ.d̂óûb́l̂éĉĺîćk̂.ńêt́/t̂áĝ/j́ŝ/ǵp̂t́.ĵś\">`. [L̂éâŕn̂ ḿôŕê](h́t̂t́p̂ś://d̂év̂él̂óp̂ér̂ś.ĝóôǵl̂é.ĉóm̂/ṕûb́l̂íŝh́êŕ-âd́ŝ-áûd́ît́ŝ/ŕêf́êŕêńĉé/âúd̂ít̂ś/l̂óâd́ŝ-ǵp̂t́-ôv́êŕ-ĥt́t̂ṕŝ)."
"audits/loads-ad-tag-over-https.js | description": {
"message": "F̂ór̂ ṕr̂ív̂áĉý âńd̂ śêćûŕît́ŷ, ál̂ẃâýŝ ĺôád̂ ǴP̂T́ ôv́êŕ ĤT́T̂ṔŜ. Ín̂śêćûŕê ṕâǵêś ŝh́ôúl̂d́ êx́p̂ĺîćît́l̂ý r̂éq̂úêśt̂ t́ĥé ĜṔT̂ śĉŕîṕt̂ śêćûŕêĺŷ. Éx̂ám̂ṕl̂é:`<ŝćr̂íp̂t́ âśŷńĉ śr̂ć=\"ĥt́t̂ṕŝ://śêćûŕêṕûb́âd́ŝ.ǵ.d̂óûb́l̂éĉĺîćk̂.ńêt́/t̂áĝ/j́ŝ/ǵp̂t́.ĵś\"> ôŕ `<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\">``. [L̂éâŕn̂ ḿôŕê](h́t̂t́p̂ś://d̂év̂él̂óp̂ér̂ś.ĝóôǵl̂é.ĉóm̂/ṕûb́l̂íŝh́êŕ-âd́ŝ-áûd́ît́ŝ/ŕêf́êŕêńĉé/âúd̂ít̂ś/l̂óâd́ŝ-ǵp̂t́-ôv́êŕ-ĥt́t̂ṕŝ)."
},
"audits/loads-gpt-over-https.js | failureDisplayValue": {
"audits/loads-ad-tag-over-https.js | failureDisplayValue": {
"message": "L̂óâd́ ĝṕt̂.j́ŝ óv̂ér̂ H́T̂T́P̂Ś"
},
"audits/loads-gpt-over-https.js | failureTitle": {
"audits/loads-ad-tag-over-https.js | failureTitle": {
"message": "L̂óâd́ ĜṔT̂ óv̂ér̂ H́T̂T́P̂Ś"
},
"audits/loads-gpt-over-https.js | title": {
"audits/loads-ad-tag-over-https.js | title": {
"message": "ĜṔT̂ t́âǵ îś l̂óâd́êd́ ôv́êŕ ĤT́T̂ṔŜ"
},
"audits/script-injected-tags.js | columnDuration": {
Expand Down Expand Up @@ -362,9 +362,6 @@
"messages/common-strings.js | NOT_APPLICABLE__NO_EVENT_MATCHING_REQ": {
"message": "N̂ó êv́êńt̂ ḿât́ĉh́êś n̂ét̂ẃôŕk̂ ŕêćôŕd̂ś"
},
"messages/common-strings.js | NOT_APPLICABLE__NO_GPT": {
"message": "ĜṔT̂ ńôt́ r̂éq̂úêśt̂éd̂"
},
"messages/common-strings.js | NOT_APPLICABLE__NO_RECORDS": {
"message": "N̂ó ŝúĉćêśŝf́ûĺ n̂ét̂ẃôŕk̂ ŕêćôŕd̂ś"
},
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module.exports = {
{path: `${PLUGIN_PATH}/audits/gpt-bids-parallel`},
{path: `${PLUGIN_PATH}/audits/idle-network-times`},
{path: `${PLUGIN_PATH}/audits/loads-gpt-from-sgdn`},
{path: `${PLUGIN_PATH}/audits/loads-gpt-over-https`},
{path: `${PLUGIN_PATH}/audits/loads-ad-tag-over-https`},
{path: `${PLUGIN_PATH}/audits/script-injected-tags`},
{path: `${PLUGIN_PATH}/audits/serial-header-bidding`},
{path: `${PLUGIN_PATH}/audits/tag-load-time`},
Expand Down Expand Up @@ -72,7 +72,7 @@ module.exports = {
// Best Practices group.
{id: 'ads-in-viewport', weight: 4, group: 'ads-best-practices'},
{id: 'async-ad-tags', weight: 2, group: 'ads-best-practices'},
{id: 'loads-gpt-over-https', weight: 1, group: 'ads-best-practices'},
{id: 'loads-ad-tag-over-https', weight: 1, group: 'ads-best-practices'},
{id: 'loads-gpt-from-sgdn', weight: 1, group: 'ads-best-practices'},
{id: 'viewport-ad-density', weight: 1, group: 'ads-best-practices'},
{id: 'ad-top-of-viewport', weight: 2, group: 'ads-best-practices'},
Expand Down
Loading