for MPP-2822: add gtag to Layout

This commit is contained in:
groovecoder 2024-06-18 10:08:50 -05:00
Родитель a624f3b41a
Коммит 25a3d3b77c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4825AB58E974B712
10 изменённых файлов: 266 добавлений и 148 удалений

Просмотреть файл

@ -4,6 +4,7 @@ FXA_PROFILE_ENDPOINT=https://profile.stage.mozaws.net/v1
FXA_BASE_ORIGIN=https://accounts.stage.mozaws.net
FXA_ACCOUNTS_ENDPOINT=https://api-accounts.stage.mozaws.net/v1
GOOGLE_ANALYTICS_ID="UA-77033033-33"
GA4_MEASUREMENT_ID="G-YXT33S87LT"
GOOGLE_APPLICATION_CREDENTIALS="gcp_key.json"
GOOGLE_CLOUD_PROFILER_CREDENTIALS_B64=""
BASKET_ORIGIN="https://basket-dev.allizom.org"

Просмотреть файл

@ -14,33 +14,34 @@ This is the Analytics plan for Firefox Relay. It documents our use of Google Ana
**Demographic:**
>From which country does the majority of our traffic originate?
> From which country does the majority of our traffic originate?
>Which browsers are most commonly used to access the Firefox Relay website?
> Which browsers are most commonly used to access the Firefox Relay website?
>Which devices are most commonly used to access the Firefox Relay website?
> Which devices are most commonly used to access the Firefox Relay website?
>Which browser is running the Firefox Relay the add-on?
> Which browser is running the Firefox Relay the add-on?
**User Behavior:**
>Do users delete aliases?
> Do users delete aliases?
>Do users create aliases?
> Do users create aliases?
>How do users create aliases? From the Relay website dashboard? The context menu? The input icon?
> How do users create aliases? From the Relay website dashboard? The context menu? The input icon?
>Do users open the extension panel?
> Do users open the extension panel?
>Do users change the forwarding settings for their aliases?
> Do users change the forwarding settings for their aliases?
>Do users who have not installed the Relay add-on, choose to install the add-on?
> Do users who have not installed the Relay add-on, choose to install the add-on?
>When do users decide to upgrade to Premium?
> When do users decide to upgrade to Premium?
 
## Extension Event Collection
Events are reported using [Google Analytics Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/v1).
We collect data for the following extension events:
@ -59,7 +60,6 @@ We collect data for the following extension events:
- When panel navigation arrow icons are clicked
### In-page events:
- When the Relay icon is injected into an email input
@ -78,12 +78,10 @@ We collect data for the following extension events:
- When the user clicks an outbound link or button
### Context Menu events:
- When an alias is generated via the context menu
### Modal events:
- When the modal opens
@ -92,13 +90,11 @@ We collect data for the following extension events:
- When "Manage All Aliases" is clicked
 
## Website Event Collection
Events are reported using [Google Analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs).
Events are reported using [Google Analytics](https://developers.google.com/analytics/devguides/collection/ga4).
We collect data for the following events:
@ -116,120 +112,125 @@ We collect data for the following events:
- When a user changes the forwarding settings for an alias
### Sign Up Buttons & Links
**`Sign In Button`** -  **`Add to Firefox Button`** -  **`Join the Waitlist Button`**
**`Sign In Button`** -  **`Add to Firefox Button`** -  **`Join the Waitlist Button`**
- When a button appears on the page
* `hitType` : event
* `eventCategory` : Button ID
* `eventAction` : View
* `eventLabel` : Page location ID.
- `hitType` : event
- `eventCategory` : Button ID
- `eventAction` : View
- `eventLabel` : Page location ID.
- When a user clicks a link or button.
* `hitType` : event
* `eventCategory` : Button or Link ID
* `eventAction` : Engage
* `eventLabel` : Page location ID.
- `hitType` : event
- `eventCategory` : Button or Link ID
- `eventAction` : Engage
- `eventLabel` : Page location ID.
### Firefox Apps menu (referred to internally as the Bento menu)
- When a user opens the Firefox Apps menu
* `hitType` : event
* `eventCategory` : bento
* `eventAction` : bento-opened
* `eventLabel` : fx-monitor
- `hitType` : event
- `eventCategory` : bento
- `eventAction` : bento-opened
- `eventLabel` : fx-monitor
- When a user closes the Firefox Apps menu
* `hitType` : event
* `eventCategory` : bento
* `eventAction` : bento-closed
* `eventLabel` : fx-monitor
- `hitType` : event
- `eventCategory` : bento
- `eventAction` : bento-closed
- `eventLabel` : fx-monitor
- When a user clicks on one of the Firefox Apps menu links
* `hitType` : event
* `eventCategory` : bento
* `eventAction` : bento-app-link-click
* `eventLabel` : link identifier
- `hitType` : event
- `eventCategory` : bento
- `eventAction` : bento-app-link-click
- `eventLabel` : link identifier
### Interview recruitment
(This is only shown occasionally, when we're trying to recruit people to join in user research.)
- When the recruitment link appears on the page
* `hitType` : event
* `eventCategory` : Recruitment
* `eventAction` : View
* `eventLabel` : Recruitment text
- `hitType` : event
- `eventCategory` : Recruitment
- `eventAction` : View
- `eventLabel` : Recruitment text
- When the recruitment link is clicked
* `hitType` : event
* `eventCategory` : Recruitment
* `eventAction` : Engage
* `eventLabel` : Recruitment text
- `hitType` : event
- `eventCategory` : Recruitment
- `eventAction` : Engage
- `eventLabel` : Recruitment text
### Net Promoter Score (NPS)/Customer Satisfaction (CSAT) surveys
- When a CSAT survey answer is selected
* `hitType` : event
* `eventCategory` : CSAT Survey
* `eventAction` : submitted
* `eventLabel` : The given answer
* `value` : A numeric value representing the given answer
* `dimension3` : Whether the given answer respresents satisfaction, neutral feeling, or dissastisfaction.
* `dimension4` : The given answer
* `metric10` : Always "1" (to count the number of answers)
* `metric11` : A numeric value representing `dimenstion4`
* `metric12` : A numeric value representing `dimenstion3`
- `hitType` : event
- `eventCategory` : CSAT Survey
- `eventAction` : submitted
- `eventLabel` : The given answer
- `value` : A numeric value representing the given answer
- `dimension3` : Whether the given answer respresents satisfaction, neutral feeling, or dissastisfaction.
- `dimension4` : The given answer
- `metric10` : Always "1" (to count the number of answers)
- `metric11` : A numeric value representing `dimenstion4`
- `metric12` : A numeric value representing `dimenstion3`
- When an NPS survey answer is selected
* `hitType` : event
* `eventCategory` : NPS Survey
* `eventAction` : submitted
* `eventLabel` : A label for the category of the given answer
* `value` : A numeric value representing the given answer
* `dimension1` : A label for the category of the given answer
* `metric10` : Always "1" (to count the number of answers)
* `metric11` : The given answer
* `metric12` : A numeric value representing the category of the given answer
- `hitType` : event
- `eventCategory` : NPS Survey
- `eventAction` : submitted
- `eventLabel` : A label for the category of the given answer
- `value` : A numeric value representing the given answer
- `dimension1` : A label for the category of the given answer
- `metric10` : Always "1" (to count the number of answers)
- `metric11` : The given answer
- `metric12` : A numeric value representing the category of the given answer
### Banners
- When a user clicks the link in one of the banners
* `hitType` : event
* `eventCategory` : Outbound
* `eventAction` : Click
* `eventLabel` : link content
- `hitType` : event
- `eventCategory` : Outbound
- `eventAction` : Click
- `eventLabel` : link content
### Links to upgrade to Premium
- When the link appears on the page
* `hitType` : event
* `eventCategory` : Purchase Button
* `eventAction` : View
* `eventLabel` : link identifier
- `hitType` : event
- `eventCategory` : Purchase Button
- `eventAction` : View
- `eventLabel` : link identifier
- When a user clicks the link
* `hitType` : event
* `eventCategory` : Purchase Button
* `eventAction` : Engage
* `eventLabel` : link identifier
- `hitType` : event
- `eventCategory` : Purchase Button
- `eventAction` : Engage
- `eventLabel` : link identifier
### The onboarding flow for new Premium subscribers
- When a button/link to continue to the next step scrolls into view
* `hitType` : event
* `eventCategory` : Premium Onboarding
* `eventAction` : View
* `eventLabel` : link identifier
- `hitType` : event
- `eventCategory` : Premium Onboarding
- `eventAction` : View
- `eventLabel` : link identifier
- When a user clicks a button/link to continue to the next step
* `hitType` : event
* `eventCategory` : Premium Onboarding
* `eventAction` : Engage
* `eventLabel` : link identifier
- `hitType` : event
- `eventCategory` : Premium Onboarding
- `eventAction` : Engage
- `eventLabel` : link identifier
## Opt Out of Google Analytics Tracking
@ -237,4 +238,4 @@ We collect data for the following events:
Before initializing Google Analytics, we check the user's browser settings for a **DNT** signal. If the **DNT** header is enabled, Analytics is never initialized and is not used to collect data for that session.
>[How do I turn on the Do Not Track feature?](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature)
> [How do I turn on the Do Not Track feature?](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature)

Просмотреть файл

@ -200,6 +200,7 @@ def _get_example_plan(plan: Literal["premium", "phones", "bundle"]) -> dict[str,
"FXA_ORIGIN": "https://accounts.firefox.com",
"PERIODICAL_PREMIUM_PRODUCT_ID": "prod_XXXXXXXXXXXXXX",
"GOOGLE_ANALYTICS_ID": "UA-########-##",
"GA4_MEASUREMENT_ID": "G-XXXXXXXXX",
"BUNDLE_PRODUCT_ID": "prod_XXXXXXXXXXXXXX",
"PHONE_PRODUCT_ID": "prod_XXXXXXXXXXXXXX",
"PERIODICAL_PREMIUM_PLANS": _get_example_plan("premium"),
@ -235,6 +236,7 @@ def runtime_data(request):
"FXA_ORIGIN": settings.FXA_BASE_ORIGIN,
"PERIODICAL_PREMIUM_PRODUCT_ID": settings.PERIODICAL_PREMIUM_PROD_ID,
"GOOGLE_ANALYTICS_ID": settings.GOOGLE_ANALYTICS_ID,
"GA4_MEASUREMENT_ID": settings.GA4_MEASUREMENT_ID,
"BUNDLE_PRODUCT_ID": settings.BUNDLE_PROD_ID,
"PHONE_PRODUCT_ID": settings.PHONE_PROD_ID,
"PERIODICAL_PREMIUM_PLANS": get_countries_info_from_request_and_mapping(

Просмотреть файл

@ -21,6 +21,7 @@
"@fluent/langneg": "^0.7.0",
"@fluent/react": "^0.15.2",
"@mozilla-protocol/core": "^17.0.1",
"@next/third-parties": "^14.2.4",
"@stripe/stripe-js": "^3.5.0",
"chokidar-cli": "^3.0.0",
"cldr-localenames-modern": "^45.0.0",

Просмотреть файл

@ -13,6 +13,7 @@ export const mockedRuntimeData: RuntimeData = {
FXA_ORIGIN: "https://fxa-mock.com",
BASKET_ORIGIN: "https://basket-mock.com",
GOOGLE_ANALYTICS_ID: "UA-123456789-0",
GA4_MEASUREMENT_ID: "G-YXT33S87LT",
PERIODICAL_PREMIUM_PRODUCT_ID: "prod_123456789",
PHONE_PRODUCT_ID: "prod_123456789",
BUNDLE_PRODUCT_ID: "prod_123456789",

Просмотреть файл

@ -0,0 +1,108 @@
// Based on: https://github.com/mozilla/blurts-server/blob/8fb1587f1af40b25fed455c79faf138c4be2d0d6/src/app/components/client/GoogleAnalyticsWorkaround.tsx
// License for this specific file:
/*
The MIT License (MIT)
Copyright (c) 2024 Vercel, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
"use client";
import { GAParams } from "@next/third-parties/dist/types/google";
import Script, { ScriptProps } from "next/script";
import { useEffect } from "react";
// We don't send Analytics events in tests:
/* c8 ignore start */
let currDataLayerName: string | undefined = undefined;
/**
* This component is based on <GoogleAnalytics> from `@next/third-parties`, but accepting a nonce
*
* @param props
*/
export const GoogleAnalyticsWorkaround = (
props: GAParams & { nonce?: ScriptProps["nonce"]; debugMode?: boolean },
) => {
const { gaId, dataLayerName = "dataLayer", nonce, debugMode } = props;
if (currDataLayerName === undefined) {
currDataLayerName = dataLayerName;
}
useEffect(() => {
if (typeof performance.mark !== "function") {
return;
}
// performance.mark is being used as a feature use signal. While it is traditionally used for performance
// benchmarking it is low overhead and thus considered safe to use in production and it is a widely available
// existing API.
// The performance measurement will be handled by Chrome Aurora
performance.mark("mark_feature_usage", {
detail: {
feature: "next-third-parties-ga",
},
});
}, []);
return (
<>
<Script
id="_next-ga-init"
dangerouslySetInnerHTML={{
__html: `
window['${dataLayerName}'] = window['${dataLayerName}'] || [];
function gtag(){window['${dataLayerName}'].push(arguments);}
gtag('js', new Date());
gtag('config', '${gaId}', { 'debug_mode': ${debugMode} });`,
}}
nonce={nonce}
/>
<Script
id="_next-ga"
src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
nonce={nonce}
/>
</>
);
};
export const sendGAEvent = (type: "event", eventName: string, args: object) => {
if (process.env.NODE_ENV === "test") {
return;
}
if (currDataLayerName === undefined) {
console.warn(`@next/third-parties: GA has not been initialized`);
return;
}
if (window[currDataLayerName]) {
window.gtag(type, eventName, args);
} else {
console.warn(
`@next/third-parties: GA dataLayer ${currDataLayerName} does not exist`,
);
}
};
/* c8 ignore stop */

Просмотреть файл

@ -32,6 +32,7 @@ import { isPhonesAvailableInCountry } from "../../functions/getPlan";
import { useL10n } from "../../hooks/l10n";
import { HolidayPromoBanner } from "./topmessage/HolidayPromoBanner";
import { isFlagActive } from "../../functions/waffle";
import { GoogleAnalyticsWorkaround } from "../GoogleAnalyticsWorkaround";
export type Props = {
children: ReactNode;
@ -285,6 +286,15 @@ export const Layout = (props: Props) => {
</footer>
</div>
</div>
{props.runtimeData !== undefined ? (
<GoogleAnalyticsWorkaround
gaId={props.runtimeData.GA4_MEASUREMENT_ID}
debugMode={
process.env.NEXT_PUBLIC_GA4_DEBUG_MODE === "true" &&
process.env.NODE_ENV !== "test"
}
/>
) : null}
</>
);
};

Просмотреть файл

@ -35,6 +35,7 @@ export type ProductData<P extends Partial<PlanData> = PlanData> = {
export type RuntimeData = {
FXA_ORIGIN: string;
GOOGLE_ANALYTICS_ID: `UA-${number}-${number}`;
GA4_MEASUREMENT_ID: `G-${string}`;
PERIODICAL_PREMIUM_PRODUCT_ID: `prod_${string}`;
PHONE_PRODUCT_ID: `prod_${string}`;
BUNDLE_PRODUCT_ID: `prod_${string}`;

112
package-lock.json сгенерированный
Просмотреть файл

@ -25,6 +25,7 @@
"@fluent/langneg": "^0.7.0",
"@fluent/react": "^0.15.2",
"@mozilla-protocol/core": "^17.0.1",
"@next/third-parties": "^14.2.4",
"@stripe/stripe-js": "^3.5.0",
"chokidar-cli": "^3.0.0",
"cldr-localenames-modern": "^45.0.0",
@ -2014,8 +2015,7 @@
"node_modules/@next/env": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz",
"integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==",
"dev": true
"integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg=="
},
"node_modules/@next/eslint-plugin-next": {
"version": "14.2.4",
@ -2079,7 +2079,6 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
@ -2095,7 +2094,6 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
@ -2111,7 +2109,6 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -2127,7 +2124,6 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -2143,7 +2139,6 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -2159,7 +2154,6 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -2175,7 +2169,6 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
@ -2191,7 +2184,6 @@
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
@ -2207,7 +2199,6 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
@ -2216,6 +2207,18 @@
"node": ">= 10"
}
},
"node_modules/@next/third-parties": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/third-parties/-/third-parties-14.2.4.tgz",
"integrity": "sha512-bf5d5m4a+Fh9syLz0Pf9Ax7LdLazlp7ur7DqX0LUMDyIx9Z/F0J/XxieklA9lRqM9KjrCVNT8Tkhg0AvotTBTQ==",
"dependencies": {
"third-party-capital": "1.0.20"
},
"peerDependencies": {
"next": "^13.0.0 || ^14.0.0",
"react": "^18.2.0"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"dev": true,
@ -2300,7 +2303,7 @@
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz",
"integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==",
"dev": true,
"devOptional": true,
"dependencies": {
"playwright": "1.43.1"
},
@ -5416,7 +5419,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dev": true,
"dependencies": {
"streamsearch": "^1.1.0"
},
@ -5462,7 +5464,6 @@
"version": "1.0.30001579",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz",
"integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==",
"dev": true,
"funding": [
{
"type": "opencollective",
@ -7812,8 +7813,7 @@
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/graphemer": {
"version": "1.4.0",
@ -8002,7 +8002,7 @@
},
"node_modules/immutable": {
"version": "4.2.2",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/import-fresh": {
@ -11771,7 +11771,6 @@
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"funding": [
{
"type": "github",
@ -11794,7 +11793,6 @@
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz",
"integrity": "sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==",
"dev": true,
"dependencies": {
"@next/env": "14.2.4",
"@swc/helpers": "0.5.5",
@ -12275,8 +12273,7 @@
"node_modules/picocolors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
"dev": true
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
},
"node_modules/picomatch": {
"version": "2.3.1",
@ -12323,7 +12320,7 @@
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz",
"integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==",
"dev": true,
"devOptional": true,
"dependencies": {
"playwright-core": "1.43.1"
},
@ -12341,7 +12338,7 @@
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz",
"integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==",
"dev": true,
"devOptional": true,
"bin": {
"playwright-core": "cli.js"
},
@ -12353,7 +12350,6 @@
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
@ -13067,7 +13063,7 @@
"version": "1.77.6",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz",
"integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==",
"dev": true,
"devOptional": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
@ -13226,7 +13222,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -13341,7 +13336,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
@ -13583,7 +13577,6 @@
},
"node_modules/styled-jsx": {
"version": "5.1.1",
"dev": true,
"license": "MIT",
"dependencies": {
"client-only": "0.0.1"
@ -14173,6 +14166,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/third-party-capital": {
"version": "1.0.20",
"resolved": "https://registry.npmjs.org/third-party-capital/-/third-party-capital-1.0.20.tgz",
"integrity": "sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA=="
},
"node_modules/tiny-glob": {
"version": "0.2.9",
"dev": true,
@ -16440,8 +16438,7 @@
"@next/env": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz",
"integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==",
"dev": true
"integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg=="
},
"@next/eslint-plugin-next": {
"version": "14.2.4",
@ -16489,65 +16486,64 @@
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz",
"integrity": "sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==",
"dev": true,
"optional": true
},
"@next/swc-darwin-x64": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz",
"integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==",
"dev": true,
"optional": true
},
"@next/swc-linux-arm64-gnu": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz",
"integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==",
"dev": true,
"optional": true
},
"@next/swc-linux-arm64-musl": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz",
"integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==",
"dev": true,
"optional": true
},
"@next/swc-linux-x64-gnu": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz",
"integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==",
"dev": true,
"optional": true
},
"@next/swc-linux-x64-musl": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz",
"integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==",
"dev": true,
"optional": true
},
"@next/swc-win32-arm64-msvc": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz",
"integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==",
"dev": true,
"optional": true
},
"@next/swc-win32-ia32-msvc": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz",
"integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==",
"dev": true,
"optional": true
},
"@next/swc-win32-x64-msvc": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz",
"integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==",
"dev": true,
"optional": true
},
"@next/third-parties": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/third-parties/-/third-parties-14.2.4.tgz",
"integrity": "sha512-bf5d5m4a+Fh9syLz0Pf9Ax7LdLazlp7ur7DqX0LUMDyIx9Z/F0J/XxieklA9lRqM9KjrCVNT8Tkhg0AvotTBTQ==",
"requires": {
"third-party-capital": "1.0.20"
}
},
"@nodelib/fs.scandir": {
"version": "2.1.5",
"dev": true,
@ -16610,7 +16606,7 @@
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz",
"integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==",
"dev": true,
"devOptional": true,
"requires": {
"playwright": "1.43.1"
}
@ -18869,7 +18865,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dev": true,
"requires": {
"streamsearch": "^1.1.0"
}
@ -18895,8 +18890,7 @@
"caniuse-lite": {
"version": "1.0.30001579",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz",
"integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==",
"dev": true
"integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA=="
},
"chalk": {
"version": "2.4.2",
@ -20306,6 +20300,7 @@
"@fluent/react": "^0.15.2",
"@mozilla-protocol/core": "^17.0.1",
"@next/eslint-plugin-next": "^14.2.3",
"@next/third-parties": "^14.2.4",
"@stripe/stripe-js": "^3.5.0",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "^6.4.6",
@ -20521,8 +20516,7 @@
"graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"graphemer": {
"version": "1.4.0",
@ -20637,7 +20631,7 @@
},
"immutable": {
"version": "4.2.2",
"dev": true
"devOptional": true
},
"import-fresh": {
"version": "3.3.0",
@ -23244,8 +23238,7 @@
"nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
},
"natural-compare": {
"version": "1.4.0",
@ -23255,7 +23248,6 @@
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz",
"integrity": "sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==",
"dev": true,
"requires": {
"@next/env": "14.2.4",
"@next/swc-darwin-arm64": "14.2.4",
@ -23559,8 +23551,7 @@
"picocolors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
"dev": true
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
},
"picomatch": {
"version": "2.3.1"
@ -23586,7 +23577,7 @@
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz",
"integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==",
"dev": true,
"devOptional": true,
"requires": {
"fsevents": "2.3.2",
"playwright-core": "1.43.1"
@ -23596,13 +23587,12 @@
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz",
"integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==",
"dev": true
"devOptional": true
},
"postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"requires": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
@ -24064,7 +24054,7 @@
"version": "1.77.6",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz",
"integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==",
"dev": true,
"devOptional": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
@ -24171,8 +24161,7 @@
"source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"dev": true
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg=="
},
"source-map-support": {
"version": "0.5.13",
@ -24262,8 +24251,7 @@
"streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"dev": true
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
},
"strict-event-emitter": {
"version": "0.5.1",
@ -24435,7 +24423,6 @@
},
"styled-jsx": {
"version": "5.1.1",
"dev": true,
"requires": {
"client-only": "0.0.1"
}
@ -24820,6 +24807,11 @@
"version": "0.2.0",
"dev": true
},
"third-party-capital": {
"version": "1.0.20",
"resolved": "https://registry.npmjs.org/third-party-capital/-/third-party-capital-1.0.20.tgz",
"integrity": "sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA=="
},
"tiny-glob": {
"version": "0.2.9",
"dev": true,

Просмотреть файл

@ -241,6 +241,7 @@ AWS_SQS_QUEUE_URL = config("AWS_SQS_QUEUE_URL", None)
RELAY_FROM_ADDRESS: str | None = config("RELAY_FROM_ADDRESS", None)
GOOGLE_ANALYTICS_ID = config("GOOGLE_ANALYTICS_ID", None)
GA4_MEASUREMENT_ID = config("GA4_MEASUREMENT_ID", None)
GOOGLE_APPLICATION_CREDENTIALS: str = config("GOOGLE_APPLICATION_CREDENTIALS", "")
GOOGLE_CLOUD_PROFILER_CREDENTIALS_B64: str = config(
"GOOGLE_CLOUD_PROFILER_CREDENTIALS_B64", ""