зеркало из https://github.com/mozilla/bedrock.git
Omit non-essential fields from RTAMO flow (Fixes #14482)
This commit is contained in:
Родитель
df4d247018
Коммит
75cab111a3
|
@ -155,6 +155,14 @@ RTAMO initially worked for only a limited subset of addons recommended by Mozill
|
|||
functionality was recently expanded by the AMO team to cover all publically listed addons,
|
||||
under a project called `Extended RTAMO (ERTAMO)`.
|
||||
|
||||
.. Important::
|
||||
|
||||
Because RTAMO is a user facing feature, expressly requested by the user from the AMO
|
||||
page, we deem the RTAMO flow as an essential/necessary use of attribution data. We do
|
||||
however limit the amount of data we collect to only what's essential for the RTAMO to
|
||||
function as a feature. Non-essential fields such as the Google Analytics client ID are
|
||||
omitted. We also continue to respect Do Not Track (DNT) as a valid opt-out signal.
|
||||
|
||||
How can visitors opt out?
|
||||
-------------------------
|
||||
|
||||
|
|
|
@ -38,40 +38,3 @@ Documentation
|
|||
See `helpers.py`_ for documentation and supported parameters for both buttons.
|
||||
|
||||
.. _helpers.py: https://github.com/mozilla/bedrock/blob/main/bedrock/firefox/templatetags/helpers.py
|
||||
|
||||
External referrers
|
||||
------------------
|
||||
|
||||
Generally we encourage other websites in the Mozilla ecosystem to link to the `/firefox/new/`_ page when
|
||||
prompting visitors to download Firefox, since it provides a consistent user experience and also benefits
|
||||
:abbr:`SEO (Search Engine Optimization)`. In some circumstances however sites may want to provide a download button that initiates a file
|
||||
download automatically when clicked. For cases like this, sites can link to the following URL:
|
||||
|
||||
.. code-block::
|
||||
|
||||
https://www.mozilla.org/firefox/download/thanks/?s=direct
|
||||
|
||||
.. Important::
|
||||
|
||||
Including the ``s=direct`` query parameter here will ensure that Windows download attribution is
|
||||
collected and recorded correctly in Telemetry. Also, make sure to **not** include the locale in
|
||||
the URL, so that bedrock can serve the most suitable language based on the visitor's browser
|
||||
preference.
|
||||
|
||||
.. Note::
|
||||
|
||||
This download URL will not automatically trigger a download in older Internet Explorer browsers. If
|
||||
that's important to your visitors, then you can use a `conditional comment`_ to provide a different link.
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<!--[if !IE]><!-->
|
||||
<a href="https://www.mozilla.org/firefox/download/thanks/?s=direct">Download Firefox</a>
|
||||
<!--<![endif]-->
|
||||
|
||||
<!--[if IE]>
|
||||
<a href="https://www.mozilla.org/firefox/new/">Download Firefox</a>
|
||||
<![endif]-->
|
||||
|
||||
.. _/firefox/new/: https://www.mozilla.org/firefox/new/
|
||||
.. _conditional comment: https://en.wikipedia.org/wiki/Conditional_comment
|
||||
|
|
|
@ -456,19 +456,31 @@ if (typeof window.Mozilla === 'undefined') {
|
|||
/**
|
||||
* Gets utm parameters and referrer information from the web page if they exist.
|
||||
* @param {String} ref - Optional referrer to facilitate testing.
|
||||
* @param {Boolean} omitNonEssentialFields - Optional flag to omit fields that are nonEssential for RTAMO.
|
||||
* @return {Object} - Stub attribution data object.
|
||||
*/
|
||||
StubAttribution.getAttributionData = function (ref) {
|
||||
StubAttribution.getAttributionData = function (
|
||||
ref,
|
||||
omitNonEssentialFields
|
||||
) {
|
||||
var params = new window._SearchParams();
|
||||
var utms = params.utmParams();
|
||||
var experiment =
|
||||
params.get('experiment') || StubAttribution.experimentName;
|
||||
var variation =
|
||||
params.get('variation') || StubAttribution.experimentVariation;
|
||||
var experiment = omitNonEssentialFields
|
||||
? null
|
||||
: params.get('experiment') || StubAttribution.experimentName;
|
||||
var variation = omitNonEssentialFields
|
||||
? null
|
||||
: params.get('variation') || StubAttribution.experimentVariation;
|
||||
var referrer = typeof ref === 'string' ? ref : document.referrer;
|
||||
var ua = StubAttribution.getUserAgent();
|
||||
var clientIDUA = StubAttribution.getUAClientID();
|
||||
var clientIDGA4 = StubAttribution.getGtagClientID();
|
||||
var ua = omitNonEssentialFields
|
||||
? 'other'
|
||||
: StubAttribution.getUserAgent();
|
||||
var clientIDUA = omitNonEssentialFields
|
||||
? null
|
||||
: StubAttribution.getUAClientID();
|
||||
var clientIDGA4 = omitNonEssentialFields
|
||||
? null
|
||||
: StubAttribution.getGtagClientID();
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
var data = {
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: This file is a special version of thanks.js that supports making a Firefox
|
||||
* attribution flow request immediately prior to triggering a download of the Firefox
|
||||
* installer. This is required in order to support Return to addons.mozilla.org (RTAMO),
|
||||
* which is a user facing feature that enables easy installation of a Firefox extension
|
||||
* as a post-install onboarding step. It is triggered via a special `?s=direct` query
|
||||
* parameter added to the `/thanks/` page when linking from an AMO page.
|
||||
*
|
||||
* Because RTAMO is a user-facing feature, expressly requested by the user from the AMO
|
||||
* page, we deem the RTAMO flow as essential/necessary. Extra measures are taken to remove
|
||||
* non-essential attribution fields and include only those required for RTAMO to function.
|
||||
*
|
||||
* DNT is still respected as an opt-out signal.
|
||||
*/
|
||||
|
||||
let timeout;
|
||||
let requestComplete = false;
|
||||
|
||||
function beginFirefoxDownload() {
|
||||
const directDownloadLink = document.getElementById('direct-download-link');
|
||||
let downloadURL;
|
||||
|
||||
// Only auto-start the download if a supported platform is detected.
|
||||
if (
|
||||
Mozilla.DownloadThanks.shouldAutoDownload(
|
||||
window.site.platform,
|
||||
window.site.fxSupported
|
||||
) &&
|
||||
typeof Mozilla.Utils !== 'undefined'
|
||||
) {
|
||||
downloadURL = Mozilla.DownloadThanks.getDownloadURL(window.site);
|
||||
|
||||
if (downloadURL) {
|
||||
// Pull download link from the download button and add to the 'Try downloading again' link.
|
||||
// Make sure the 'Try downloading again' link is well formatted! (issue 9615)
|
||||
if (directDownloadLink && directDownloadLink.href) {
|
||||
directDownloadLink.href = downloadURL;
|
||||
directDownloadLink.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
try {
|
||||
Mozilla.TrackProductDownload.handleLink(event);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// Start the platform-detected download a second after DOM ready event.
|
||||
Mozilla.Utils.onDocumentReady(() => {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
Mozilla.TrackProductDownload.sendEventFromURL(
|
||||
downloadURL
|
||||
);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
window.location.href = downloadURL;
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
// Make sure we only initiate the download once!
|
||||
clearTimeout(timeout);
|
||||
if (requestComplete) {
|
||||
return;
|
||||
}
|
||||
requestComplete = true;
|
||||
|
||||
// Fire GA event to log attribution success
|
||||
// UA
|
||||
window.dataLayer.push({
|
||||
event: 'non-interaction',
|
||||
eAction: 'direct-attribution',
|
||||
eLabel: 'success'
|
||||
});
|
||||
// GA4
|
||||
window.dataLayer.push({
|
||||
event: 'widget_action',
|
||||
type: 'direct-attribution',
|
||||
action: 'success',
|
||||
non_interaction: true
|
||||
});
|
||||
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
|
||||
function onTimeout() {
|
||||
// Make sure we only initiate the download once!
|
||||
clearTimeout(timeout);
|
||||
if (requestComplete) {
|
||||
return;
|
||||
}
|
||||
requestComplete = true;
|
||||
|
||||
// Fire GA event to log attribution timeout
|
||||
// UA
|
||||
window.dataLayer.push({
|
||||
event: 'non-interaction',
|
||||
eAction: 'direct-attribution',
|
||||
eLabel: 'timeout'
|
||||
});
|
||||
// GA4
|
||||
window.dataLayer.push({
|
||||
event: 'widget_action',
|
||||
type: 'direct-attribution',
|
||||
action: 'timeout',
|
||||
non_interaction: true
|
||||
});
|
||||
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
|
||||
function initAttribution() {
|
||||
// We pass omitNonEssentialFields=true here to only include the attribution fields
|
||||
// required for RTAMO to function as a user facing feature.
|
||||
const data = Mozilla.StubAttribution.getAttributionData(null, true);
|
||||
|
||||
// Make sure we check referrer for AMO (issue 11467)
|
||||
if (
|
||||
data &&
|
||||
Mozilla.StubAttribution.withinAttributionRate() &&
|
||||
Mozilla.StubAttribution.hasValidData(data)
|
||||
) {
|
||||
Mozilla.StubAttribution.successCallback = onSuccess;
|
||||
Mozilla.StubAttribution.timeoutCallback = onTimeout;
|
||||
// We don't want to delay the download indefinitely for a stub attribution call,
|
||||
// so we only wait up to an additional 2 seconds (on top of GA) before downloading.
|
||||
timeout = setTimeout(onTimeout, 2000);
|
||||
Mozilla.StubAttribution.requestAuthentication(data);
|
||||
} else {
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If visitor already has a cookie, or does not meet the typical requirements fo
|
||||
* stub attribution, then we can start the download as normal. If requirements *are*
|
||||
* met and the visitor does *not* have a cookie, then attempt to make the attribution
|
||||
* call before starting the download.
|
||||
*/
|
||||
if (
|
||||
typeof Mozilla.StubAttribution !== 'undefined' &&
|
||||
Mozilla.StubAttribution.meetsRequirements() &&
|
||||
!Mozilla.StubAttribution.hasCookie()
|
||||
) {
|
||||
initAttribution();
|
||||
} else {
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
|
||||
// Bug 1354334 - add a hint for test automation that page has loaded.
|
||||
document.getElementsByTagName('html')[0].classList.add('download-ready');
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var timeout;
|
||||
var requestComplete = false;
|
||||
|
||||
function beginFirefoxDownload() {
|
||||
var directDownloadLink = document.getElementById(
|
||||
'direct-download-link'
|
||||
);
|
||||
var downloadURL;
|
||||
|
||||
// Only auto-start the download if a supported platform is detected.
|
||||
if (
|
||||
Mozilla.DownloadThanks.shouldAutoDownload(
|
||||
window.site.platform,
|
||||
window.site.fxSupported
|
||||
) &&
|
||||
typeof Mozilla.Utils !== 'undefined'
|
||||
) {
|
||||
downloadURL = Mozilla.DownloadThanks.getDownloadURL(window.site);
|
||||
|
||||
if (downloadURL) {
|
||||
// Pull download link from the download button and add to the 'Try downloading again' link.
|
||||
// Make sure the 'Try downloading again' link is well formatted! (issue 9615)
|
||||
if (directDownloadLink && directDownloadLink.href) {
|
||||
directDownloadLink.href = downloadURL;
|
||||
directDownloadLink.addEventListener(
|
||||
'click',
|
||||
function (event) {
|
||||
try {
|
||||
Mozilla.TrackProductDownload.handleLink(event);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// Start the platform-detected download a second after DOM ready event.
|
||||
Mozilla.Utils.onDocumentReady(function () {
|
||||
setTimeout(function () {
|
||||
try {
|
||||
Mozilla.TrackProductDownload.sendEventFromURL(
|
||||
downloadURL
|
||||
);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
window.location.href = downloadURL;
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
// Make sure we only initiate the download once!
|
||||
clearTimeout(timeout);
|
||||
if (requestComplete) {
|
||||
return;
|
||||
}
|
||||
requestComplete = true;
|
||||
|
||||
// Fire GA event to log attribution success
|
||||
// UA
|
||||
window.dataLayer.push({
|
||||
event: 'non-interaction',
|
||||
eAction: 'direct-attribution',
|
||||
eLabel: 'success'
|
||||
});
|
||||
// GA4
|
||||
window.dataLayer.push({
|
||||
event: 'widget_action',
|
||||
type: 'direct-attribution',
|
||||
action: 'success',
|
||||
non_interaction: true
|
||||
});
|
||||
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
|
||||
function onTimeout() {
|
||||
// Make sure we only initiate the download once!
|
||||
clearTimeout(timeout);
|
||||
if (requestComplete) {
|
||||
return;
|
||||
}
|
||||
requestComplete = true;
|
||||
|
||||
// Fire GA event to log attribution timeout
|
||||
// UA
|
||||
window.dataLayer.push({
|
||||
event: 'non-interaction',
|
||||
eAction: 'direct-attribution',
|
||||
eLabel: 'timeout'
|
||||
});
|
||||
// GA4
|
||||
window.dataLayer.push({
|
||||
event: 'widget_action',
|
||||
type: 'direct-attribution',
|
||||
action: 'timeout',
|
||||
non_interaction: true
|
||||
});
|
||||
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
|
||||
/**
|
||||
* If visitor already has a cookie, or does not meet the typical requirements fo
|
||||
* stub attribution, then we can start the download as normal. If requirements *are*
|
||||
* met and the visitor does *not* have a cookie, then attempt to make the attribution
|
||||
* call before starting the download.
|
||||
*/
|
||||
if (
|
||||
typeof Mozilla.StubAttribution !== 'undefined' &&
|
||||
Mozilla.StubAttribution.meetsRequirements() &&
|
||||
!Mozilla.StubAttribution.hasCookie()
|
||||
) {
|
||||
// Wait for GA to load so that we can pass along visit ID.
|
||||
Mozilla.StubAttribution.waitForGoogleAnalyticsThen(function () {
|
||||
var data = Mozilla.StubAttribution.getAttributionData();
|
||||
|
||||
// make sure we check referrer for AMO (issue 11467)
|
||||
if (
|
||||
data &&
|
||||
Mozilla.StubAttribution.withinAttributionRate() &&
|
||||
Mozilla.StubAttribution.hasValidData(data)
|
||||
) {
|
||||
Mozilla.StubAttribution.successCallback = onSuccess;
|
||||
Mozilla.StubAttribution.timeoutCallback = onTimeout;
|
||||
// We don't want to delay the download indefinitely for a stub attribution call,
|
||||
// so we only wait up to an additional 2 seconds (on top of GA) before downloading.
|
||||
timeout = setTimeout(onTimeout, 2000);
|
||||
Mozilla.StubAttribution.requestAuthentication(data);
|
||||
} else {
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
beginFirefoxDownload();
|
||||
}
|
||||
|
||||
// Bug 1354334 - add a hint for test automation that page has loaded.
|
||||
document.getElementsByTagName('html')[0].classList.add('download-ready');
|
||||
})();
|
|
@ -1326,7 +1326,7 @@
|
|||
{
|
||||
"files": [
|
||||
"js/firefox/new/common/thanks.js",
|
||||
"js/firefox/new/common/thanks-direct.js"
|
||||
"js/firefox/new/common/thanks-direct.es6.js"
|
||||
],
|
||||
"name": "firefox_new_thanks_direct"
|
||||
},
|
||||
|
|
|
@ -775,6 +775,48 @@ describe('stub-attribution.js', function () {
|
|||
const result = Mozilla.StubAttribution.getAttributionData(referrer);
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
|
||||
it('should omit non-essential attribution data when `omitNonEssentialFields=true` is passed', function () {
|
||||
const referrer = 'https://addons.mozilla.org/';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
const utms = {
|
||||
utm_source: 'addons.mozilla.org',
|
||||
utm_medium: 'referral',
|
||||
utm_campaign: 'non-fx-button',
|
||||
utm_content: 'rta%3Acm9uaW4td2FsbGV0QGF4aWVpbmZpbml0eS5jb20'
|
||||
};
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
const data = {
|
||||
utm_source: 'addons.mozilla.org',
|
||||
utm_medium: 'referral',
|
||||
utm_campaign: 'non-fx-button',
|
||||
utm_content: 'rta%3Acm9uaW4td2FsbGV0QGF4aWVpbmZpbml0eS5jb20',
|
||||
referrer: 'https://addons.mozilla.org/',
|
||||
ua: 'other',
|
||||
dlsource: DLSOURCE
|
||||
};
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
spyOn(window._SearchParams.prototype, 'utmParams').and.returnValue(
|
||||
utms
|
||||
);
|
||||
spyOn(window._SearchParams.prototype, 'get').and.callFake(
|
||||
function (key) {
|
||||
return key === 'experiment' ? 'firefox-new' : 1;
|
||||
}
|
||||
);
|
||||
spyOn(Mozilla.StubAttribution, 'getUserAgent').and.returnValue(
|
||||
'chrome'
|
||||
);
|
||||
const result = Mozilla.StubAttribution.getAttributionData(
|
||||
referrer,
|
||||
true
|
||||
);
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('requestAuthentication', function () {
|
||||
|
|
Загрузка…
Ссылка в новой задаче