diff --git a/index.html b/index.html
index 981d63b..4ebf942 100644
--- a/index.html
+++ b/index.html
@@ -19,6 +19,14 @@
Leather - Earn
+
diff --git a/package.json b/package.json
index 24a7ab6..ce08543 100644
--- a/package.json
+++ b/package.json
@@ -19,11 +19,13 @@
"dependencies": {
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
+ "@leather.io/analytics": "^3.0.3",
"@leather.io/tokens": "0.12.1",
"@leather.io/ui": "1.37.0",
"@noble/hashes": "1.3.2",
"@reduxjs/toolkit": "1.9.7",
"@scure/base": "1.1.3",
+ "@segment/analytics-next": "^1.76.0",
"@stacks/auth": "7.0.2",
"@stacks/blockchain-api-client": "7.3.2",
"@stacks/common": "7.0.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a996ad9..cc5afdb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,6 +19,9 @@ importers:
'@emotion/styled':
specifier: 11.11.0
version: 11.11.0(@emotion/react@11.11.1(@types/react@18.2.13)(react@18.3.1))(@types/react@18.2.13)(react@18.3.1)
+ '@leather.io/analytics':
+ specifier: ^3.0.3
+ version: 3.0.3
'@leather.io/tokens':
specifier: 0.12.1
version: 0.12.1
@@ -34,6 +37,9 @@ importers:
'@scure/base':
specifier: 1.1.3
version: 1.1.3
+ '@segment/analytics-next':
+ specifier: ^1.76.0
+ version: 1.76.0
'@stacks/auth':
specifier: 7.0.2
version: 7.0.2
@@ -1793,6 +1799,9 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@leather.io/analytics@3.0.3':
+ resolution: {integrity: sha512-ZGcycLWi4h2nQmANx0ufy2Ah84hSllT206s8cT6zFQZUilTLtQS68L3IBIbp0GTnczKLR5Z8H2evvEI3UbEC0w==}
+
'@leather.io/constants@0.13.5':
resolution: {integrity: sha512-FOh/F/g8WepB8HfoTXsMB/BYcm/F6INPEpyEZc3ljzaN0mLwVLO1kwgMTFU9Pq7tQlITvyWiyGHcB7OYovLoUQ==}
@@ -1820,6 +1829,14 @@ packages:
'@leather.io/utils@0.20.0':
resolution: {integrity: sha512-Ot0oOYMku4oy3218W3Tt0ip0xjMyegOxFONqOyt/WSZe9xzTiXXUq0u3D8jwa851ZEOSCB7TgOO5RMzWK0lkLg==}
+ '@lukeed/csprng@1.1.0':
+ resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
+ engines: {node: '>=8'}
+
+ '@lukeed/uuid@2.0.1':
+ resolution: {integrity: sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==}
+ engines: {node: '>=8'}
+
'@noble/hashes@1.1.5':
resolution: {integrity: sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==}
@@ -3212,6 +3229,27 @@ packages:
'@scure/bip39@1.1.0':
resolution: {integrity: sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==}
+ '@segment/analytics-core@1.8.0':
+ resolution: {integrity: sha512-6CrccsYRY33I3mONN2ZW8SdBpbLtu1Ict3xR+n0FemYF5RB/jG7pW6jOvDXULR8kuYMzMmGOP4HvlyUmf3qLpg==}
+
+ '@segment/analytics-generic-utils@1.2.0':
+ resolution: {integrity: sha512-DfnW6mW3YQOLlDQQdR89k4EqfHb0g/3XvBXkovH1FstUN93eL1kfW9CsDcVQyH3bAC5ZsFyjA/o/1Q2j0QeoWw==}
+
+ '@segment/analytics-next@1.76.0':
+ resolution: {integrity: sha512-4n4vMvX0+bfypFWuu/UJNenT/Gv2+04SsjvnQL1eBd1hngKBV56EkCW+PCJyFRQQ7BnzHgWF4mY+vOPkdoke3A==}
+
+ '@segment/analytics.js-video-plugins@0.2.1':
+ resolution: {integrity: sha512-lZwCyEXT4aaHBLNK433okEKdxGAuyrVmop4BpQqQSJuRz0DglPZgd9B/XjiiWs1UyOankg2aNYMN3VcS8t4eSQ==}
+
+ '@segment/facade@3.4.10':
+ resolution: {integrity: sha512-xVQBbB/lNvk/u8+ey0kC/+g8pT3l0gCT8O2y9Z+StMMn3KAFAQ9w8xfgef67tJybktOKKU7pQGRPolRM1i1pdA==}
+
+ '@segment/isodate-traverse@1.1.1':
+ resolution: {integrity: sha512-+G6e1SgAUkcq0EDMi+SRLfT48TNlLPF3QnSgFGVs0V9F3o3fq/woQ2rHFlW20W0yy5NnCUH0QGU3Am2rZy/E3w==}
+
+ '@segment/isodate@1.0.3':
+ resolution: {integrity: sha512-BtanDuvJqnACFkeeYje7pWULVv8RgZaqKHWwGFnL/g/TH/CcZjkIVTfGDp/MAxmilYHUkrX70SqwnYSTNEaN7A==}
+
'@segment/loosely-validate-event@2.0.0':
resolution: {integrity: sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==}
@@ -4620,6 +4658,10 @@ packages:
resolution: {integrity: sha512-JhcR/+KIjkkjiU8yEpaB/USlzVi3i5whwOjpIRNGi9svKEXZSe+Qp6IWAjFjv+2GViAoDRCUv/QLNziQxsLqDg==}
engines: {node: '>=12'}
+ dset@3.1.4:
+ resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
+ engines: {node: '>=4'}
+
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@@ -5685,6 +5727,10 @@ packages:
join-component@1.1.0:
resolution: {integrity: sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==}
+ js-cookie@3.0.1:
+ resolution: {integrity: sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==}
+ engines: {node: '>=12'}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -6299,6 +6345,9 @@ packages:
nested-error-stacks@2.0.1:
resolution: {integrity: sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==}
+ new-date@1.0.3:
+ resolution: {integrity: sha512-0fsVvQPbo2I18DT2zVHpezmeeNYV2JaJSrseiHLc17GNOxJzUdx5mvSigPu8LtIfZSij5i1wXnXFspEs2CD6hA==}
+
nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
@@ -6389,6 +6438,9 @@ packages:
resolution: {integrity: sha512-zYDMnnNrFi/1Tqh0vo3PE4p97Tpl9/4MP2k2ECvkbLOZzQuAYZJLTUYVLZb7hJhbhjT+JJxAwBGS8iu5hCSd1w==}
engines: {node: '>=18'}
+ obj-case@0.2.1:
+ resolution: {integrity: sha512-PquYBBTy+Y6Ob/O2574XHhDtHJlV1cJHMCgW+rDRc9J5hhmRelJB3k5dTK/3cVmFVtzvAKuENeuLpoyTzMzkOg==}
+
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@@ -7831,6 +7883,12 @@ packages:
undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ unfetch@3.1.2:
+ resolution: {integrity: sha512-L0qrK7ZeAudGiKYw6nzFjnJ2D5WHblUBwmHIqtPS6oKUd+Hcpk7/hKsSmcHsTlpd1TbTNsiRBUKRq3bHLNIqIw==}
+
+ unfetch@4.2.0:
+ resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
+
unicode-canonical-property-names-ecmascript@2.0.1:
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
engines: {node: '>=4'}
@@ -10186,6 +10244,8 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@leather.io/analytics@3.0.3': {}
+
'@leather.io/constants@0.13.5':
dependencies:
'@leather.io/models': 0.22.0
@@ -10289,6 +10349,12 @@ snapshots:
'@leather.io/rpc': 2.1.20
bignumber.js: 9.1.2
+ '@lukeed/csprng@1.1.0': {}
+
+ '@lukeed/uuid@2.0.1':
+ dependencies:
+ '@lukeed/csprng': 1.1.0
+
'@noble/hashes@1.1.5': {}
'@noble/hashes@1.3.2': {}
@@ -12683,6 +12749,49 @@ snapshots:
'@noble/hashes': 1.1.5
'@scure/base': 1.1.3
+ '@segment/analytics-core@1.8.0':
+ dependencies:
+ '@lukeed/uuid': 2.0.1
+ '@segment/analytics-generic-utils': 1.2.0
+ dset: 3.1.4
+ tslib: 2.8.1
+
+ '@segment/analytics-generic-utils@1.2.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@segment/analytics-next@1.76.0':
+ dependencies:
+ '@lukeed/uuid': 2.0.1
+ '@segment/analytics-core': 1.8.0
+ '@segment/analytics-generic-utils': 1.2.0
+ '@segment/analytics.js-video-plugins': 0.2.1
+ '@segment/facade': 3.4.10
+ dset: 3.1.4
+ js-cookie: 3.0.1
+ node-fetch: 2.7.0
+ tslib: 2.8.1
+ unfetch: 4.2.0
+ transitivePeerDependencies:
+ - encoding
+
+ '@segment/analytics.js-video-plugins@0.2.1':
+ dependencies:
+ unfetch: 3.1.2
+
+ '@segment/facade@3.4.10':
+ dependencies:
+ '@segment/isodate-traverse': 1.1.1
+ inherits: 2.0.4
+ new-date: 1.0.3
+ obj-case: 0.2.1
+
+ '@segment/isodate-traverse@1.1.1':
+ dependencies:
+ '@segment/isodate': 1.0.3
+
+ '@segment/isodate@1.0.3': {}
+
'@segment/loosely-validate-event@2.0.0':
dependencies:
component-type: 1.2.2
@@ -14411,6 +14520,8 @@ snapshots:
dotenv@16.4.6: {}
+ dset@3.1.4: {}
+
eastasianwidth@0.2.0: {}
ee-first@1.1.1: {}
@@ -15714,6 +15825,8 @@ snapshots:
join-component@1.1.0: {}
+ js-cookie@3.0.1: {}
+
js-tokens@4.0.0: {}
js-yaml@3.14.1:
@@ -16508,6 +16621,10 @@ snapshots:
nested-error-stacks@2.0.1: {}
+ new-date@1.0.3:
+ dependencies:
+ '@segment/isodate': 1.0.3
+
nice-try@1.0.5: {}
no-case@3.0.4:
@@ -16609,6 +16726,8 @@ snapshots:
ob1@0.80.5: {}
+ obj-case@0.2.1: {}
+
object-assign@4.1.1: {}
object-inspect@1.13.3: {}
@@ -18203,6 +18322,10 @@ snapshots:
undici-types@5.26.5: {}
+ unfetch@3.1.2: {}
+
+ unfetch@4.2.0: {}
+
unicode-canonical-property-names-ecmascript@2.0.1: {}
unicode-match-property-ecmascript@2.0.0:
diff --git a/src/app.tsx b/src/app.tsx
index 45e2f40..2f70ce6 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -37,6 +37,7 @@ import { StackIncrease } from './pages/stacking/stack-increase/stack-increase';
import { StartDirectStacking } from './pages/stacking/start-direct-stacking/start-direct-stacking';
import { StartLiquidStacking } from './pages/stacking/start-liquid-stacking/start-liquid-stacking';
import { StartPooledStacking } from './pages/stacking/start-pooled-stacking/start-pooled-stacking';
+import { initAnalytics } from '@utils/analytics';
const queryClient = new QueryClient({
defaultOptions: {
@@ -49,6 +50,9 @@ const queryClient = new QueryClient({
function Root() {
useEffect(() => void loadFonts(), []);
+ useEffect(() => {
+ void initAnalytics();
+ }, []);
const [searchParams] = useSearchParams();
const chain = searchParams.get('chain');
diff --git a/src/components/auth-provider/auth-provider.tsx b/src/components/auth-provider/auth-provider.tsx
index 6e42cb7..0fe7755 100644
--- a/src/components/auth-provider/auth-provider.tsx
+++ b/src/components/auth-provider/auth-provider.tsx
@@ -13,6 +13,7 @@ import { validateStacksAddress as isValidStacksAddress } from '@stacks/transacti
import { APP_DETAILS } from 'src/constants';
import { useStacksNetwork } from '@hooks/use-stacks-network';
+import { analytics } from '@utils/analytics';
const appConfig = new AppConfig(['store_write']);
const userSession = new UserSession({ appConfig });
@@ -68,6 +69,13 @@ export function AuthProvider({ children }: Props) {
return;
}
setIsSigningIn(true);
+
+ const provider = window.StacksProvider?.getProductInfo?.()?.name ?? 'none';
+
+ analytics.untypedTrack('earn_sign_in_started', {
+ provider,
+ });
+
showConnect({
userSession,
appDetails: APP_DETAILS,
@@ -76,10 +84,17 @@ export function AuthProvider({ children }: Props) {
return provider.id === 'LeatherProvider';
}),
onFinish() {
+ const provider = window.StacksProvider?.getProductInfo?.()?.name ?? 'none';
+ analytics.untypedTrack('earn_sign_in_completed', {
+ provider,
+ });
setIsSigningIn(false);
setIsSignedIn(true);
},
onCancel() {
+ analytics.untypedTrack('earn_sign_in_cancelled', {
+ provider,
+ });
setIsSigningIn(false);
},
} as AuthOptions);
diff --git a/src/env.d.ts b/src/env.d.ts
index ceb50c1..b6ba3f8 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -11,9 +11,6 @@ interface ImportMetaEnv {
*/
readonly VITE_COMMIT_SHA?: string;
- /**
- * TODO: document where to find the key
- */
readonly VITE_SEGMENT_WRITE_KEY?: string;
/**
diff --git a/src/pages/choose-stacking-method/components/bridge-to-sbtc-card.tsx b/src/pages/choose-stacking-method/components/bridge-to-sbtc-card.tsx
index 4f88bcf..bed3910 100644
--- a/src/pages/choose-stacking-method/components/bridge-to-sbtc-card.tsx
+++ b/src/pages/choose-stacking-method/components/bridge-to-sbtc-card.tsx
@@ -36,7 +36,7 @@ export function BridgeToSBTCCard(props: ChooseStackingMethodLayoutProps) {
The version of Leather installed does not support this feature. Please update
- Leather (6.55+) to bridge sBTC.
+ Leather (6.56+) to bridge sBTC.
diff --git a/src/pages/choose-stacking-method/components/enroll-for-sbtc-rewards.tsx b/src/pages/choose-stacking-method/components/enroll-for-sbtc-rewards.tsx
index 418f099..5fc466b 100644
--- a/src/pages/choose-stacking-method/components/enroll-for-sbtc-rewards.tsx
+++ b/src/pages/choose-stacking-method/components/enroll-for-sbtc-rewards.tsx
@@ -10,6 +10,7 @@ import { BaseDrawer } from '@components/drawer/base-drawer';
import { openExternalLink } from '@utils/external-links';
import { ChooseStackingMethodLayoutProps } from '../types';
+import { analytics } from '@utils/analytics';
export function EnrollForSBTCRewardsCard(props: ChooseStackingMethodLayoutProps) {
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -46,6 +47,7 @@ export function EnrollForSBTCRewardsCard(props: ChooseStackingMethodLayoutProps)
onClick={() => {
// TODO: Implement enrollment logic with contract call
setIsModalOpen(false);
+ analytics.untypedTrack('sbtc_earn_enrollment_started');
openExternalLink('https://bitcoinismore.org');
}}
>
diff --git a/src/pages/choose-stacking-method/hooks/index.ts b/src/pages/choose-stacking-method/hooks/index.ts
index f496608..c03ff96 100644
--- a/src/pages/choose-stacking-method/hooks/index.ts
+++ b/src/pages/choose-stacking-method/hooks/index.ts
@@ -3,6 +3,7 @@ import { useNavigate } from '@hooks/use-navigate';
import { ChooseStackingMethodLayoutProps } from '../types';
import { hasExistingCommitment } from '../utils';
+import { analytics } from '@utils/analytics';
export const usePooledStackingButton = (props: ChooseStackingMethodLayoutProps) => {
const navigate = useNavigate();
@@ -77,7 +78,9 @@ export function useLeatherSbtcBridgeButton(setUpdateModalOpen: (open: boolean) =
base: 'BTC',
quote: 'sBTC',
});
+ analytics.untypedTrack('sbtc_bridge_requested');
} catch (error) {
+ analytics.untypedTrack('sbtc_bridge_request_failed');
console.error('Error requesting openSwap', error);
setUpdateModalOpen(true);
}
diff --git a/src/pages/stacking/start-pooled-stacking/utils-delegate-stx.ts b/src/pages/stacking/start-pooled-stacking/utils-delegate-stx.ts
index f63ec8a..eb891e5 100644
--- a/src/pages/stacking/start-pooled-stacking/utils-delegate-stx.ts
+++ b/src/pages/stacking/start-pooled-stacking/utils-delegate-stx.ts
@@ -159,7 +159,7 @@ export function createHandleSubmit({
setIsContractCallExtensionPageOpen,
navigate,
}: CreateHandleSubmitArgs) {
- return async function handleSubmit(values: EditingFormValues) {
+ return async function handleSubmit(values: EditingFormValues, onFinish?: () => void) {
// TODO: handle thrown errors
const [poxInfo, stackingContract] = await Promise.all([
client.getPoxInfo(),
@@ -172,6 +172,7 @@ export function createHandleSubmit({
...delegateStxOptions,
onFinish() {
setIsContractCallExtensionPageOpen(false);
+ onFinish?.();
navigate('../pooled-stacking-info');
},
onCancel() {
diff --git a/src/pages/stacking/start-pooled-stacking/utils.ts b/src/pages/stacking/start-pooled-stacking/utils.ts
index 508389d..5ebace7 100644
--- a/src/pages/stacking/start-pooled-stacking/utils.ts
+++ b/src/pages/stacking/start-pooled-stacking/utils.ts
@@ -7,13 +7,14 @@ import {
getPoxWrapperContract,
requiresAllowContractCaller,
} from './utils-preset-pools';
+import { analytics } from '@utils/analytics';
interface CreateHandleSubmitArgs {
hasUserConfirmedPoolWrapperContract: PoolWrapperAllowanceState;
setHasUserConfirmedPoolWrapperContract: React.Dispatch<
React.SetStateAction
>;
- handleDelegateStxSubmit: (val: EditingFormValues) => Promise;
+ handleDelegateStxSubmit: (val: EditingFormValues, onFinish?: () => void) => Promise;
handleAllowContractCallerSubmit: ({
poxWrapperContract,
onFinish,
@@ -32,8 +33,23 @@ export function createHandleSubmit({
if (values.poolName && requiresAllowContractCaller(values.poolName)) {
const poxWrapperContract = getPoxWrapperContract(values.poolName, network);
const networkInstance = getNetworkInstance(network);
+
+ analytics.untypedTrack('stacking_initiated', {
+ pool_or_protocol_name: values.poolName,
+ network: networkInstance,
+ stacking_type: 'pooled',
+ });
+
+ const trackStackCompleted = () => {
+ analytics.untypedTrack('stacking_completed', {
+ pool_or_protocol_name: values.poolName,
+ network: networkInstance,
+ stacking_type: 'pooled',
+ });
+ };
+
if (hasUserConfirmedPoolWrapperContract[networkInstance]?.[poxWrapperContract]) {
- handleDelegateStxSubmit(values);
+ handleDelegateStxSubmit(values, trackStackCompleted);
return;
} else {
handleAllowContractCallerSubmit({
@@ -46,6 +62,7 @@ export function createHandleSubmit({
[poxWrapperContract]: true,
},
});
+ trackStackCompleted();
},
});
return;
diff --git a/src/utils/analytics.ts b/src/utils/analytics.ts
new file mode 100644
index 0000000..e2a092c
--- /dev/null
+++ b/src/utils/analytics.ts
@@ -0,0 +1,36 @@
+import { AnalyticsBrowser } from '@segment/analytics-next';
+
+import { configureAnalyticsClient } from '@leather.io/analytics';
+
+const segmentClient = new AnalyticsBrowser();
+
+export const analytics = configureAnalyticsClient({
+ client: segmentClient,
+ defaultProperties: {
+ platform: 'web',
+ },
+});
+
+export function initAnalytics() {
+ if (!import.meta.env.VITE_SEGMENT_WRITE_KEY) {
+ console.log('No Segment write key found');
+ return;
+ }
+
+ return analytics.client.load(
+ { writeKey: import.meta.env.VITE_SEGMENT_WRITE_KEY ?? '' },
+ {
+ integrations: {
+ 'Segment.io': {
+ deliveryStrategy: {
+ strategy: 'batching',
+ config: {
+ size: 10,
+ timeout: 5000,
+ },
+ },
+ },
+ },
+ }
+ );
+}