diff --git a/controllers/home.js b/controllers/home.js index 63018858e..2ef38c66f 100644 --- a/controllers/home.js +++ b/controllers/home.js @@ -4,7 +4,12 @@ const AppConstants = require("../app-constants"); const DB = require("../db/DB"); const HIBP = require("../hibp"); const { scanResult } = require("../scan-results"); -const { generatePageToken, getExperimentFlags } = require("./utils"); +const { + generatePageToken, + getExperimentBranch, + getExperimentFlags, + getUTMContents, +} = require("./utils"); const EXPERIMENTS_ENABLED = (AppConstants.EXPERIMENT_ACTIVE === "1"); @@ -17,7 +22,6 @@ function _getFeaturedBreach(allBreaches, breachQueryValue) { } async function home(req, res) { - const formTokens = { pageToken: AppConstants.PAGE_TOKEN_TIMER > 0 ? generatePageToken(req) : "", csrfToken: req.csrfToken(), @@ -30,9 +34,18 @@ async function home(req, res) { return res.redirect("/user/dashboard"); } + // Rewrites the /share/{COLOR} links to / + if (req.session.redirectHome) { + req.session.redirectHome = false; + return res.redirect("/"); + } + + // Note - If utmOverrides get set, they are unenrolled from the experiment + const utmOverrides = getUTMContents(req); const experimentFlags = getExperimentFlags(req, EXPERIMENTS_ENABLED); if (req.query.breach) { + featuredBreach = _getFeaturedBreach(req.app.locals.breaches, req.query.breach); if (!featuredBreach) { @@ -53,6 +66,7 @@ async function home(req, res) { pageToken: formTokens.pageToken, csrfToken: formTokens.csrfToken, experimentFlags, + utmOverrides, }); } @@ -63,6 +77,7 @@ async function home(req, res) { pageToken: formTokens.pageToken, csrfToken: formTokens.csrfToken, experimentFlags, + utmOverrides, }); } diff --git a/controllers/utils.js b/controllers/utils.js index 3162076a2..67c7ddcfb 100644 --- a/controllers/utils.js +++ b/controllers/utils.js @@ -182,9 +182,23 @@ function getExperimentBranch(req, sorterNum = false, language = false, variation } +function getUTMContents(req) { + if (!req) { + throw new Error("No request available"); + } + + // If UTMs are set previously, set them again. + if (req.session.utmOverrides) { + return req.session.utmOverrides; + } + + req.session.utmOverrides = false; + return false; +} + function getExperimentFlags(req, EXPERIMENTS_ENABLED) { if (!req) { - throw new Error("No request availabe"); + throw new Error("No request available"); } if (req.session.experimentFlags && EXPERIMENTS_ENABLED) { @@ -208,4 +222,5 @@ module.exports = { hasUserSignedUpForRelay, getExperimentBranch, getExperimentFlags, + getUTMContents, }; diff --git a/middleware.js b/middleware.js index 75db54de8..45198793c 100644 --- a/middleware.js +++ b/middleware.js @@ -15,6 +15,7 @@ const { FXA } = require("./lib/fxa"); const { FluentError } = require("./locale-utils"); const mozlog = require("./log"); +const HIBP = require("./hibp"); const log = mozlog("middleware"); @@ -173,6 +174,63 @@ async function requireSessionUser(req, res, next) { next(); } +function getShareUTMs(req, res, next) { + // Step 1: See if the user needs to be redirected to the homepage or to a breach-detail page. + const generalShareUrls = [ + "/share/orange", //Header + "/share/purple", // Footer + "/share/blue", // user/dashboard + "/share/", + ]; + + if (generalShareUrls.includes(req.url)) { + // If not breach specific, redirect to "/" + req.session.redirectHome = true; + } + + const inNotInActiveExperiment = (!req.session.experimentFlags); + + // Excluse user from experiment if they don't have any experimentFlags set already. + if (inNotInActiveExperiment) { + + // Step 2: Determine if user needs to have share-link UTMs set + const colors = [ + "orange", //Header + "purple", // Footer + "blue", // user/dashboard + ]; + + const urlArray = req.url.split("/"); + const color = urlArray.slice(-1)[0]; + + req.session.utmOverrides = { + campaignName: "shareLinkTraffic", + campaignTerm: "default", + }; + + // Set Color Var in UTM + if (color.length && colors.includes(color)) { + req.session.utmOverrides.campaignTerm = color; + } + + if (color.length && !colors.includes(color)) { + const allBreaches = req.app.locals.breaches; + const breachName = color; + const featuredBreach = HIBP.getBreachByName(allBreaches, breachName); + + if (featuredBreach) { + req.session.utmOverrides.campaignTerm = featuredBreach.Name; + } + } + + // Exclude share users + req.session.experimentFlags = { + excludeFromExperiment: true, + }; + } + + next(); +} module.exports = { @@ -185,4 +243,5 @@ module.exports = { clientErrorHandler, errorHandler, requireSessionUser, + getShareUTMs, }; diff --git a/routes/home.js b/routes/home.js index f719405a2..88014e2af 100644 --- a/routes/home.js +++ b/routes/home.js @@ -5,10 +5,17 @@ const csrf = require("csurf"); const {home, getAboutPage, getAllBreaches, getBentoStrings, getSecurityTips, notFound} = require("../controllers/home"); +const { getShareUTMs } = require("../middleware"); + const router = express.Router(); const csrfProtection = csrf(); router.get("/", csrfProtection, home); +router.get("/share/orange", csrfProtection, getShareUTMs, home); +router.get("/share/purple", csrfProtection, getShareUTMs, home); +router.get("/share/blue", csrfProtection, getShareUTMs, home); +router.get("/share/:breach", csrfProtection, getShareUTMs, home); +router.get("/share/", csrfProtection, getShareUTMs, home); router.get("/about", getAboutPage); router.get("/breaches", getAllBreaches); router.get("/security-tips", getSecurityTips);