From d33b14c06e08844a7da69c870e72e052a7cb32e7 Mon Sep 17 00:00:00 2001 From: Alex Gibson Date: Tue, 6 Feb 2024 14:40:35 +0000 Subject: [PATCH] Add mobile app store redirector (Issue #14172) --- bedrock/firefox/redirects.py | 34 ++++++++++++++++++++- bedrock/redirects/util.py | 18 ++++++++++++ tests/redirects/map_globalconf.py | 49 +++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/bedrock/firefox/redirects.py b/bedrock/firefox/redirects.py index d579d24cdf3..42206e25191 100644 --- a/bedrock/firefox/redirects.py +++ b/bedrock/firefox/redirects.py @@ -2,7 +2,7 @@ # 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/. -from bedrock.redirects.util import no_redirect, platform_redirector, redirect +from bedrock.redirects.util import mobile_app_redirector, no_redirect, platform_redirector, redirect def firefox_mobile_faq(request, *args, **kwargs): @@ -17,6 +17,36 @@ def firefox_channel(*args, **kwargs): return platform_redirector("firefox.channel.desktop", "firefox.channel.android", "firefox.channel.ios") +def mobile_app(request, *args, **kwargs): + qs = request.META.get("QUERY_STRING", "") + campaign = None + product = "firefox" + + product_options = ["firefox", "focus", "klar"] + + campaign_options = [ + "firefox-whatsnew", + "firefox-whatsnew-120", + "firefox-whatsnew-122", + "firefox-welcome-6", + "firefox-welcome-17", + "firefox-browsers-mobile-get-app", + "firefox-browsers-mobile-android", + "firefox-browsers-mobile-ios", + "firefox-browsers-mobile-focus", + ] + + for p in product_options: + if f"product={p}" in qs: + product = p + + for c in campaign_options: + if f"campaign={c}" in qs: + campaign = c + + return mobile_app_redirector(request, product, campaign) + + redirectpatterns = ( # overrides # issue 8096 @@ -562,4 +592,6 @@ def firefox_channel(*args, **kwargs): # issue 13732 redirect(r"^firefox/welcome/3/?$", "firefox.accounts"), redirect(r"^firefox/mobile/get-app/?$", "firefox.browsers.mobile.get-app"), + # issue 14172 + redirect(r"^firefox/browsers/mobile/app/?$", mobile_app, cache_timeout=0, query=False), ) diff --git a/bedrock/redirects/util.py b/bedrock/redirects/util.py index c9527b7fc9c..0553050989a 100644 --- a/bedrock/redirects/util.py +++ b/bedrock/redirects/util.py @@ -6,6 +6,7 @@ from collections import defaultdict from urllib.parse import parse_qs, urlencode +from django.conf import settings from django.http import ( HttpResponseGone, HttpResponsePermanentRedirect, @@ -86,6 +87,23 @@ def decider(request, *args, **kwargs): return decider +def mobile_app_redirector(request, product, campaign): + android_re = re.compile(r"\bAndroid\b", flags=re.I) + value = request.headers.get("User-Agent", "") + + if android_re.search(value): + base_url = getattr(settings, f"GOOGLE_PLAY_{product.upper()}_LINK") + params = "&referrer=utm_source%3Dwww.mozilla.org%26utm_medium%3Dreferral%26utm_campaign%3D{cmp}" + else: + base_url = getattr(settings, f"APPLE_APPSTORE_{product.upper()}_LINK").replace("/{country}/", "/") + params = "?pt=373246&ct={cmp}&mt=8" + + if campaign: + return base_url + params.format(cmp=campaign) + else: + return base_url + + def no_redirect(pattern, locale_prefix=True, re_flags=None): """ Return a url matcher that will stop the redirect middleware and force diff --git a/tests/redirects/map_globalconf.py b/tests/redirects/map_globalconf.py index 48b83f27b32..b1eacf84b8f 100644 --- a/tests/redirects/map_globalconf.py +++ b/tests/redirects/map_globalconf.py @@ -1231,5 +1231,54 @@ url_test("/foundation/annualreport/{,2022/}", "https://stateof.mozilla.org/"), # Issue 14186 url_test("/privacy/firefox-monitor/", "/privacy/subscription-services/"), + # Issue 14172 + url_test( + "/firefox/browsers/mobile/app/?product=firefox", + "https://play.google.com/store/apps/details?id=org.mozilla.firefox", + req_headers=UA_ANDROID, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=firefox", + "https://apps.apple.com/app/apple-store/id989804926", + req_headers=UA_IOS, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=firefox&campaign=firefox-whatsnew", + "https://play.google.com/store/apps/details?id=org.mozilla.firefox&referrer=utm_source%3Dwww.mozilla.org%26utm_medium%3Dreferral%26utm_campaign%3Dfirefox-whatsnew", + req_headers=UA_ANDROID, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=firefox&campaign=firefox-whatsnew", + "https://apps.apple.com/app/apple-store/id989804926?pt=373246&ct=firefox-whatsnew&mt=8", + req_headers=UA_IOS, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=focus&campaign=firefox-browsers-mobile-focus", + "https://play.google.com/store/apps/details?id=org.mozilla.focus&referrer=utm_source%3Dwww.mozilla.org%26utm_medium%3Dreferral%26utm_campaign%3Dfirefox-browsers-mobile-focus", + req_headers=UA_ANDROID, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=focus&campaign=firefox-browsers-mobile-focus", + "https://apps.apple.com/app/apple-store/id1055677337?pt=373246&ct=firefox-browsers-mobile-focus&mt=8", + req_headers=UA_IOS, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=klar&campaign=firefox-browsers-mobile-focus", + "https://play.google.com/store/apps/details?id=org.mozilla.klar&referrer=utm_source%3Dwww.mozilla.org%26utm_medium%3Dreferral%26utm_campaign%3Dfirefox-browsers-mobile-focus", + req_headers=UA_ANDROID, + resp_headers={"Cache-Control": "max-age=0"}, + ), + url_test( + "/firefox/browsers/mobile/app/?product=klar&campaign=firefox-browsers-mobile-focus", + "https://apps.apple.com/app/apple-store/id1073435754?pt=373246&ct=firefox-browsers-mobile-focus&mt=8", + req_headers=UA_IOS, + resp_headers={"Cache-Control": "max-age=0"}, + ), ) )