Skip to content

Commit 2e4dab1

Browse files
authored
chore: update support.metamask urls to track utm source (#27331)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Adds UTM parameters (`utm_source=mobile_app`) to outbound links in the MetaMask Mobile app, specifically updating the support page link to `https://support.metamask.io?utm_source=mobile_app`. Currently all mobile app traffic appears as "Direct" in analytics. This change enables proper attribution to distinguish mobile users from extension users and other sources. The solution updates link URLs in relevant components (help screens, settings, etc.) while maintaining identical user experience. ## **Changelog** CHANGELOG entry: Added UTM parameters to mobile app links for improved analytics tracking ## **Related issues** ## **Manual testing steps** ```gherkin Feature: UTM parameters on support links Scenario: Support link contains UTM parameters Given MetaMask Mobile app is running on test build And user navigates to Settings → Help When user taps the "Get help" / support link Then link URL contains "?utm_source=mobile_app" Scenario: External browser opens with correct UTM parameters Given MetaMask Mobile app is running on test build And user navigates to a screen with support link When user taps support link Then external browser opens https://support.metamask.io?utm_source=mobile_app ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches many user-facing outbound support links and `AppConstants` URL wiring; low functional complexity, but mistakes could send users to incorrect help pages or break deep-link constants. > > **Overview** > Adds a `MOBILE_UTM` suffix and expands `app/constants/urls.ts` to provide canonical, UTM-tagged MetaMask support/article URLs (plus shared deep-link base constants like `MM_UNIVERSAL_LINK_HOST` and `MM_ANDROID_BUNDLE_ID`). > > Updates a wide set of screens/modals (Support/Help, onboarding, password reset, staking/earn, perps, ramp region/eligibility, network verification, error boundary, etc.) to **stop using hardcoded support URLs** and instead reference these centralized constants, with corresponding test expectation updates. Also switches `AppConstants` to import several URL values and bundle/universal-link constants from `constants/urls` to avoid duplication. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6ff5d04. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 61a0b3c commit 2e4dab1

36 files changed

Lines changed: 203 additions & 147 deletions

File tree

app/components/UI/Compliance/contexts/AccessRestrictedContext.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
useAccessRestrictedModal,
77
} from './AccessRestrictedContext';
88
import { AccessRestrictedModalSelectorsIDs } from '../AccessRestrictedModal/AccessRestrictedModal.testIds';
9+
import { METAMASK_SUPPORT_URL } from '../../../../constants/urls';
910

1011
const mockNavigate = jest.fn();
1112
jest.mock('@react-navigation/native', () => ({
@@ -128,7 +129,7 @@ describe('AccessRestrictedContext', () => {
128129
expect.any(String),
129130
expect.objectContaining({
130131
params: expect.objectContaining({
131-
url: 'https://support.metamask.io',
132+
url: METAMASK_SUPPORT_URL,
132133
}),
133134
}),
134135
);

app/components/UI/Earn/components/Tron/TronStakingLearnMoreModal/TronStakingLearnMoreModal.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
createMockEventBuilder,
1010
createMockUseAnalyticsHook,
1111
} from '../../../../../../util/test/analyticsMock';
12+
import { TRON_STAKING_FAQ_URL } from '../../../../../../constants/urls';
1213

1314
const mockNavigate = jest.fn();
1415

@@ -185,7 +186,7 @@ describe('TronStakingLearnMoreModal', () => {
185186
expect(mockNavigate).toHaveBeenCalledWith('Webview', {
186187
screen: 'SimpleWebview',
187188
params: {
188-
url: 'https://support.metamask.io/metamask-portfolio/move-crypto/stake/',
189+
url: TRON_STAKING_FAQ_URL,
189190
},
190191
});
191192
});

app/components/UI/Earn/components/Tron/TronStakingLearnMoreModal/index.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ import {
1919
StakingInfoBodyText,
2020
StakingInfoStrings,
2121
} from '../../../../Stake/components/LearnMoreModal';
22-
23-
const TRON_STAKING_FAQ_URL =
24-
'https://support.metamask.io/metamask-portfolio/move-crypto/stake/';
22+
import { TRON_STAKING_FAQ_URL } from '../../../../../../constants/urls';
2523

2624
const TronStakingLearnMoreModal = () => {
2725
const { styles } = useStyles(styleSheet, {});
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { LENDING_FAQ_URL } from '../../../../constants/urls';
2+
13
export const EARN_URLS = {
2-
LENDING_FAQ: 'https://support.metamask.io/manage-crypto/earn/lending/',
4+
LENDING_FAQ: LENDING_FAQ_URL,
35
};

app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { CustomNetworkInformation } from './NetworkVerificationInfo.types';
2525
import { ScrollView } from 'react-native-gesture-handler';
2626
import { useSelector } from 'react-redux';
2727
import { selectUseSafeChainsListValidation } from '../../../selectors/preferencesController';
28+
import { ADD_CUSTOM_NETWORK_ARTCILE } from '../../../constants/urls';
2829
import {
2930
ButtonSize,
3031
ButtonVariants,
@@ -41,7 +42,6 @@ import { convertHexToDecimal } from '@metamask/controller-utils';
4142
import { isValidASCIIURL, toPunycodeURL } from '../../../util/url';
4243
import { PopularList } from '../../../util/networks/customNetworks';
4344
import { MISSMATCH_RPC_URL_TEST_ID } from './NetworkVerificationInfo.constants';
44-
import { ADD_CUSTOM_NETWORK_ARTCILE } from '../../../constants/urls';
4545

4646
interface Alert {
4747
alertError: string;
@@ -99,9 +99,7 @@ const NetworkVerificationInfo = ({
9999
}, [matchingPopularNetwork, customNetworkInformation.rpcUrl]);
100100

101101
const goToLearnMore = () => {
102-
Linking.openURL(
103-
'https://support.metamask.io/networks-and-sidechains/managing-networks/verifying-custom-network-information/',
104-
);
102+
Linking.openURL(ADD_CUSTOM_NETWORK_ARTCILE);
105103
};
106104

107105
useEffect(() => setAlerts(alertsFromProps), [alertsFromProps]);

app/components/UI/OptinMetrics/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {
5151
import { setupSentry } from '../../../util/sentry/utils';
5252
import PrivacyIllustration from '../../../images/privacy_metrics_illustration.png';
5353
import Device from '../../../util/device';
54+
import { HOWTO_MANAGE_METAMETRICS } from '../../../constants/urls';
5455
import type { OptinMetricsRouteParams } from './OptinMetrics.types';
5556
import {
5657
useNavigation,
@@ -257,7 +258,7 @@ const OptinMetrics = () => {
257258
const openLearnMore = useCallback(
258259
() =>
259260
onPressLink({
260-
url: 'https://support.metamask.io/configure/privacy/how-to-manage-your-metametrics-settings/',
261+
url: HOWTO_MANAGE_METAMETRICS,
261262
title: 'How to manage your MetaMetrics settings',
262263
}),
263264
[onPressLink],

app/components/UI/Perps/components/PerpsTutorialCarousel/PerpsTutorialCarousel.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { useStyles } from '../../../../../component-library/hooks';
3232
import Routes from '../../../../../constants/navigation/Routes';
3333
import NavigationService from '../../../../../core/NavigationService';
3434
import { EXTERNAL_LINK_TYPE } from '../../../../../constants/browser';
35+
import { PERPS_LEARN_MORE_URL } from '../../../../../constants/urls';
3536
import { MetaMetricsEvents } from '../../../../../core/Analytics';
3637
import {
3738
PERPS_EVENT_PROPERTY,
@@ -379,7 +380,7 @@ const PerpsTutorialCarousel: React.FC = () => {
379380
NavigationService.navigation.navigate(Routes.BROWSER.HOME, {
380381
screen: Routes.BROWSER.VIEW,
381382
params: {
382-
newTabUrl: 'https://support.metamask.io/manage-crypto/trade/perps',
383+
newTabUrl: PERPS_LEARN_MORE_URL,
383384
linkType: EXTERNAL_LINK_TYPE,
384385
timestamp: Date.now(),
385386
fromPerps: true,

app/components/UI/Perps/constants/perpsConfig.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
*/
1111
import type { Hex } from '@metamask/utils';
1212
import { TokenI } from '../../Tokens/types';
13+
import {
14+
PERPS_ADL_URL,
15+
METAMASK_SUPPORT_URL,
16+
} from '../../../../constants/urls';
1317

1418
/** Address used to represent "Perps balance" as the payment token (synthetic option). */
1519
export const PERPS_BALANCE_PLACEHOLDER_ADDRESS =
@@ -191,7 +195,7 @@ export const LEARN_MORE_CONFIG = {
191195
* Contact support button configuration (matches Settings behavior)
192196
*/
193197
export const SUPPORT_CONFIG = {
194-
Url: 'https://support.metamask.io',
198+
Url: METAMASK_SUPPORT_URL,
195199
TitleKey: 'perps.support.title',
196200
DescriptionKey: 'perps.support.description',
197201
} as const;
@@ -210,8 +214,7 @@ export const FEEDBACK_CONFIG = {
210214
* Links to specific MetaMask support articles for Perps features
211215
*/
212216
export const PERPS_SUPPORT_ARTICLES_URLS = {
213-
AdlUrl:
214-
'https://support.metamask.io/manage-crypto/trade/perps/leverage-and-liquidation/#what-is-auto-deleveraging-adl',
217+
AdlUrl: PERPS_ADL_URL,
215218
} as const;
216219

217220
/**

app/components/UI/ProtectYourWalletModal/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { connect } from 'react-redux';
2323
import { protectWalletModalNotVisible } from '../../../actions/user';
2424
import { strings } from '../../../../locales/i18n';
2525
import scaling from '../../../util/scaling';
26+
import { LEARN_MORE_URL } from '../../../constants/urls';
2627
import { MetaMetricsEvents } from '../../../core/Analytics/MetaMetrics.events';
2728
import { ProtectWalletModalSelectorsIDs } from './ProtectWalletModal.testIds';
2829
import { analytics } from '../../../util/analytics/analytics';
@@ -63,7 +64,7 @@ class ProtectYourWalletModal extends PureComponent {
6364
this.props.navigation.navigate('Webview', {
6465
screen: 'SimpleWebview',
6566
params: {
66-
url: 'https://support.metamask.io/privacy-and-security/basic-safety-and-security-tips-for-metamask/',
67+
url: LEARN_MORE_URL,
6768
title: strings('protect_wallet_modal.title'),
6869
},
6970
});

app/components/UI/ProtectYourWalletModal/index.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import renderWithProvider from '../../../util/test/renderWithProvider';
88
import { strings } from '../../../../locales/i18n';
99
import { ProtectWalletModalSelectorsIDs } from './ProtectWalletModal.testIds';
1010
import { analytics } from '../../../util/analytics/analytics';
11+
import { LEARN_MORE_URL } from '../../../constants/urls';
1112

1213
jest.mock('../../../util/analytics/analytics', () => ({
1314
analytics: {
@@ -120,7 +121,7 @@ describe('ProtectYourWalletModal', () => {
120121
expect(mockNavigation.navigate).toHaveBeenCalledWith('Webview', {
121122
screen: 'SimpleWebview',
122123
params: {
123-
url: 'https://support.metamask.io/privacy-and-security/basic-safety-and-security-tips-for-metamask/',
124+
url: LEARN_MORE_URL,
124125
title: strings('protect_wallet_modal.title'),
125126
},
126127
});

0 commit comments

Comments
 (0)