Skip to content
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/audits/ad-blocking-tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const LongTasks = require('../computed/long-tasks');
const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {getAttributableUrl} = require('../utils/tasks');
const {isGpt} = require('../utils/resource-classification');
const {isAdScript} = require('../utils/resource-classification');
const {URL} = require('url');

const UIStrings = {
Expand Down Expand Up @@ -124,7 +124,7 @@ class AdBlockingTasks extends Audit {
continue;
}
const scriptUrl = getAttributableUrl(longTask);
if (scriptUrl && isGpt(new URL(scriptUrl))) {
if (scriptUrl && isAdScript(new URL(scriptUrl))) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const RenderBlockingResources = require('lighthouse/lighthouse-core/audits/byte-
const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {getPageStartTime} = require('../utils/network-timing');
const {isGptTag} = require('../utils/resource-classification');
const {isAdTag} = require('../utils/resource-classification');
const {URL} = require('url');

const UIStrings = {
Expand Down Expand Up @@ -88,7 +88,7 @@ class AdRenderBlockingResources extends RenderBlockingResources {
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
const hasTag = !!networkRecords.find((req) => isGptTag(new URL(req.url)));
const hasTag = !!networkRecords.find((req) => isAdTag(new URL(req.url)));
if (!hasTag) {
return auditNotApplicable.NoTag;
}
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/audits/ad-top-of-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
const i18n = require('lighthouse/lighthouse-core/lib/i18n/i18n');
const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {isGptIframe} = require('../utils/resource-classification');
const {isAdIframe} = require('../utils/resource-classification');

const UIStrings = {
title: 'No ad found at the very top of the viewport',
Expand Down Expand Up @@ -67,7 +67,7 @@ class AdTopOfViewport extends Audit {
*/
static audit(artifacts) {
const viewport = artifacts.ViewportDimensions;
const slots = artifacts.IFrameElements.filter(isGptIframe)
const slots = artifacts.IFrameElements.filter(isAdIframe)
.filter((slot) => slot.isVisible && !slot.isFixed)
.map((slot) => ({
midpoint: slot.clientRect.top + slot.clientRect.height / 2,
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/audits/ads-in-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');

const i18n = require('lighthouse/lighthouse-core/lib/i18n/i18n');
const {isAdIframe} = require('../utils/resource-classification');
const {isBoxInViewport} = require('../utils/geometry');
const {isGptIframe} = require('../utils/resource-classification');

const UIStrings = {
title: 'Few or no ads loaded outside viewport',
Expand Down Expand Up @@ -67,7 +67,7 @@ class AdsInViewport extends Audit {
static audit(artifacts) {
const viewport = artifacts.ViewportDimensions;
const slots = artifacts.IFrameElements
.filter((iframe) => isGptIframe(iframe) && iframe.isVisible);
.filter((iframe) => isAdIframe(iframe) && iframe.isVisible);

if (!slots.length) {
return auditNotApplicable.NoVisibleSlots;
Expand Down
12 changes: 6 additions & 6 deletions lighthouse-plugin-publisher-ads/audits/async-ad-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ const MainResource = require('lighthouse/lighthouse-core/computed/main-resource'
const NetworkRecords = require('lighthouse/lighthouse-core/computed/network-records');
const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {isGptTag, isStaticRequest} = require('../utils/resource-classification');
const {isAdTag, isStaticRequest} = require('../utils/resource-classification');
const {URL} = require('url');

const UIStrings = {
title: 'GPT tag is loaded asynchronously',
failureTitle: 'Load GPT asynchronously',
description: 'Loading the GPT tag synchronously blocks content rendering ' +
title: 'Ad tag is loaded asynchronously',
failureTitle: 'Load ad tag asynchronously',
description: 'Loading the ad tag synchronously blocks content rendering ' +
'until the tag is fetched and loaded. Consider using the `async` attribute ' +
'to load gpt.js asynchronously. [Learn more](' +
'to load gpt.js and/or adsbygoogle.js asynchronously. [Learn more](' +
'https://developers.google.com/publisher-ads-audits/reference/audits/async-ad-tags' +
').',
};
Expand Down Expand Up @@ -72,7 +72,7 @@ class AsyncAdTags extends Audit {
const mainResource =
await MainResource.request({URL: artifacts.URL, devtoolsLog}, context);
const tagReqs = networkRecords
.filter((req) => isGptTag(new URL(req.url)))
.filter((req) => isAdTag(new URL(req.url)))
.filter((req) => req.frameId === mainResource.frameId);

if (!tagReqs.length) {
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/audits/full-width-slots.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const i18n = require('lighthouse/lighthouse-core/lib/i18n/i18n');
const NetworkRecords = require('lighthouse/lighthouse-core/computed/network-records');
const {auditNotApplicable} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {isGptAdRequest} = require('../utils/resource-classification');
const {isAdRequest} = require('../utils/resource-classification');
const {URL} = require('url');

const UIStrings = {
Expand Down Expand Up @@ -61,7 +61,7 @@ class FullWidthSlots extends Audit {

/** @type {Array<URL>} */
const adRequestUrls = networkRecords
.filter(isGptAdRequest)
.filter(isAdRequest)
.map((record) => new URL(record.url));

if (!adRequestUrls.length) {
Expand Down
7 changes: 4 additions & 3 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,9 +73,9 @@ 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;
return auditNotApplicable.NoGpt;
}

const bids = network.filter(isBidRequest)
Expand Down Expand Up @@ -118,3 +118,4 @@ class GptBidsInParallel extends Audit {
}

module.exports = GptBidsInParallel;
module.exports.UIStrings = UIStrings;
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,40 @@ 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. ' +
'GPT Example: `<script async ' +
'src=\"https://securepubads.g.doubleclick.net/tag/js/gpt.js\">` ' +
'AdSense Example: `<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 +72,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;
11 changes: 6 additions & 5 deletions lighthouse-plugin-publisher-ads/audits/script-injected-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@ const HEADINGS = [
];

const STATICALLY_LOADABLE_TAGS = [
/amazon-adsystem.com\/aax2\/apstag.js/,
/js-sec.indexww.com\/ht\/p\/.*.js/,
/pubads.g.doubleclick.net\/tag\/js\/gpt.js/,
/static.criteo.net\/js\/.*\/publishertag.js/,
/www.googletagservices.com\/tag\/js\/gpt.js/,
/amazon-adsystem\.com\/aax2\/apstag.js/,
/js-sec\.indexww\.com\/ht\/p\/.*\.js/,
/pubads\.g\.doubleclick\.net\/tag\/js\/gpt\.js/,
/static\.criteo\.net\/js\/.*\/publishertag\.js/,
/www\.googletagservices\.com\/tag\/js\/gpt\.js/,
/pagead2\.googlesyndication\.com\/pagead\/js\/adsbygoogle\.js/,
];

/**
Expand Down
6 changes: 3 additions & 3 deletions lighthouse-plugin-publisher-ads/audits/tag-load-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ const {Audit} = require('lighthouse');
const UIStrings = {
title: 'Tag load time',
failureTitle: 'Reduce tag load time',
description: 'This metric measures the time for the Google Publisher ' +
'Tag\'s implementation script (pubads_impl.js) to load after the page ' +
'loads. [Learn more](' +
description: 'This metric measures the time for the ad tag\'s ' +
'implementation script (pubads_impl.js for GPT; adsbygoogle.js for ' +
'AdSense) to load after the page loads. [Learn more](' +
'https://developers.google.com/publisher-ads-audits/reference/audits/metrics' +
').',
displayValue: '{timeInMs, number, seconds} s',
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/audits/viewport-ad-density.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const i18n = require('lighthouse/lighthouse-core/lib/i18n/i18n');
const {auditNotApplicable, auditError} = require('../messages/common-strings');
const {Audit} = require('lighthouse');
const {boxViewableArea} = require('../utils/geometry');
const {isGptIframe} = require('../utils/resource-classification');
const {isAdIframe} = require('../utils/resource-classification');

const UIStrings = {
title: 'Ad density in initial viewport is within recommended range',
Expand Down Expand Up @@ -57,7 +57,7 @@ class ViewportAdDensity extends Audit {
static audit(artifacts) {
const viewport = artifacts.ViewportDimensions;
const slots = artifacts.IFrameElements.filter(
(slot) => isGptIframe(slot) && slot.isVisible);
(slot) => isAdIframe(slot) && slot.isVisible);

if (!slots.length) {
return auditNotApplicable.NoVisibleSlots;
Expand Down
12 changes: 9 additions & 3 deletions lighthouse-plugin-publisher-ads/computed/ad-paint-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const AdLanternMetric = require('./ad-lantern-metric');
const ComputedMetric = require('lighthouse/lighthouse-core/computed/metrics/metric');
// @ts-ignore
const makeComputedArtifact = require('lighthouse/lighthouse-core/computed/computed-artifact');
const {isGptAdRequest, isGptIframe} = require('../utils/resource-classification');
const {isAdRequest, isAdIframe} = require('../utils/resource-classification');

/**
* Returns the frame ID of the given event, if present.
Expand Down Expand Up @@ -54,7 +54,7 @@ function getAdIframes(data) {
if (!iframeElements) {
return [];
}
return iframeElements.filter(isGptIframe);
return iframeElements.filter(isAdIframe);
}

/** Computes simulated first ad request time using Lantern. */
Expand All @@ -71,11 +71,17 @@ class LanternAdPaintTime extends AdLanternMetric {
const adFrameIds = new Set(iframes.map(
/** @param {Artifacts['IFrameElement']} s */
(s) => s.frame && s.frame.id));
console.log('------- adFrameIds ---------'); // DO NOT SUBMIT - remove before merging PR
console.dir(adFrameIds); // DO NOT SUBMIT - remove before merging PR
const adResponseMs = AdLanternMetric.findNetworkTiming(
nodeTimings, isGptAdRequest).endTime;
nodeTimings, isAdRequest).endTime;
console.log('------- adResponseMs ---------'); // DO NOT SUBMIT - remove before merging PR
console.dir(adResponseMs); // DO NOT SUBMIT - remove before merging PR
// TODO: filter out pixels from resources
const firstAdResource = AdLanternMetric.findNetworkTiming(
nodeTimings, (request) => adFrameIds.has(request.frameId)).endTime;
console.log('------- firstAdResource ---------'); // DO NOT SUBMIT - remove before merging PR
console.dir(firstAdResource); // DO NOT SUBMIT - remove before merging PR
const timeInMs = adResponseMs + firstAdResource;
return {timeInMs, nodeTimings};
}
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-plugin-publisher-ads/computed/ad-request-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const ComputedMetric = require('lighthouse/lighthouse-core/computed/metrics/metr
// @ts-ignore
const makeComputedArtifact = require('lighthouse/lighthouse-core/computed/computed-artifact');
const {getAdStartTime, getPageStartTime} = require('../utils/network-timing');
const {isGptAdRequest} = require('../utils/resource-classification');
const {isAdRequest} = require('../utils/resource-classification');

// @ts-ignore
// eslint-disable-next-line max-len
Expand All @@ -35,7 +35,7 @@ class LanternAdRequestTime extends AdLanternMetric {
static getEstimateFromSimulation(simulationResult, extras) {
const {nodeTimings} = simulationResult;
const timeInMs = AdLanternMetric.findNetworkTiming(
nodeTimings, isGptAdRequest).startTime;
nodeTimings, isAdRequest).startTime;
return {timeInMs, nodeTimings};
}
}
Expand Down
Loading