Skip to content

Commit

Permalink
Merge pull request #3707 from mozilla/save-utms-for-firefox-visits-mp…
Browse files Browse the repository at this point in the history
…p-3262

MPP-3262: save utms in cookies to restore after redirects
  • Loading branch information
groovecoder authored Aug 1, 2023
2 parents 36256bb + bb64d17 commit a8667c2
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 2 deletions.
30 changes: 30 additions & 0 deletions frontend/src/functions/cookies.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import ReactGa from "react-ga";

export function getCookie(cookieId: string): string | undefined {
if (typeof document === "undefined") {
// When server-side rendering:
Expand Down Expand Up @@ -41,3 +43,31 @@ export function clearCookie(cookieId: string) {
export function getCsrfToken(): string | undefined {
return getCookie("csrftoken");
}

export function convertUtmCookieToGaField(
utmCookie: string,
): ReactGa.FieldsObject {
/*
* To preserve utm url param values thru FxA redirects, the server-side
* middleware:StoreUtmsInCookie stores utm params in cookies with this format:
* utm_medium=firefox-desktop;
* utm_source=modal;
* utm_content=manage-masks-global;
*
* analytics.js traffic source field names are in this format:
* campaignMedium
* campaignSource
* campaignContent
*
* So, convert the cookie names and values to GA field names & values
*/
const campaignField = utmCookie.split("=");
const campaignFieldName = campaignField[0].replace("utm_", "");
const capitalizedCampaignFieldName =
campaignFieldName.charAt(0).toUpperCase() + campaignFieldName.slice(1);
const campaignFieldValue = campaignField[1];
const gaField: ReactGa.FieldsObject = {};
const gaFieldName = `campaign${capitalizedCampaignFieldName}`;
gaField[gaFieldName] = campaignFieldValue;
return gaField;
}
13 changes: 11 additions & 2 deletions frontend/src/pages/_app.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { initialiseApiMocks } from "../apiMocks/initialise";
import { mockIds } from "../apiMocks/mockData";
import { useIsLoggedIn } from "../hooks/session";
import "@stripe/stripe-js";
import { clearCookie, convertUtmCookieToGaField } from "../functions/cookies";

if (process.env.NEXT_PUBLIC_MOCK_API === "true") {
initialiseApiMocks();
Expand Down Expand Up @@ -65,11 +66,19 @@ function MyApp({ Component, pageProps }: AppProps) {
titleCase: false,
debug: process.env.NEXT_PUBLIC_DEBUG === "true",
});
ReactGa.set({
const gaFields: ReactGa.FieldsObject = {
anonymizeIp: true,
transport: "beacon",
});
};
const cookies = document.cookie.split("; ");
cookies.forEach((item) => {
if (item.trim().startsWith("utm_")) {
const cookieId = item.split("=")[0];
Object.assign(gaFields, convertUtmCookieToGaField(item));
clearCookie(cookieId);
}
});
ReactGa.set(gaFields);
const gaEventCookies = cookies.filter((item) =>
item.trim().startsWith("server_ga_event:"),
);
Expand Down
18 changes: 18 additions & 0 deletions privaterelay/middleware.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import datetime, timezone
import time
from urllib.parse import urlparse, parse_qs

import markus

Expand All @@ -12,6 +13,23 @@
metrics = markus.get_metrics("fx-private-relay")


class StoreUtmsInCookie:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
# Store utm_ values in cookie so we can send them in GA pings after redirecting
# thru FxA flow.
response = self.get_response(request)
if "utm_" in request.get_full_path():
parsed_url = urlparse(request.build_absolute_uri())
parsed_qs = parse_qs(parsed_url.query)
for param in parsed_qs:
if param.startswith("utm_"):
response.set_cookie(param, parsed_qs[param][0])
return response


class RedirectRootIfLoggedIn:
def __init__(self, get_response):
self.get_response = get_response
Expand Down
1 change: 1 addition & 0 deletions privaterelay/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ def _get_initial_middleware() -> list[str]:
MIDDLEWARE += [
"django.middleware.security.SecurityMiddleware",
"csp.middleware.CSPMiddleware",
"privaterelay.middleware.StoreUtmsInCookie",
"privaterelay.middleware.RedirectRootIfLoggedIn",
"privaterelay.middleware.RelayStaticFilesMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
Expand Down

0 comments on commit a8667c2

Please sign in to comment.