From a9c4a425307bc5bb3917affb52d55eccccbf8ffc Mon Sep 17 00:00:00 2001 From: samuelea Date: Mon, 20 Oct 2025 21:32:58 -0400 Subject: [PATCH 1/7] added event for forte payments --- .../ForteController.tsx | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx index 38d823d62..ed1b13eeb 100644 --- a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx +++ b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx @@ -1,12 +1,15 @@ +import { useAnalyticsContext } from '@0xsequence/connect' import { useConfig } from '@0xsequence/hooks' import { useEffect, useState } from 'react' import { fetchFortePaymentStatus } from '../../api/data.js' +import { EVENT_SOURCE } from '../../constants/index.js' import { FortePaymentControllerProvider, useEnvironmentContext, type FortePaymentData } from '../../contexts/index.js' const POLLING_TIME = 10 * 1000 export const ForteController = ({ children }: { children: React.ReactNode }) => { + const { analytics } = useAnalyticsContext() const [fortePaymentData, setFortePaymentData] = useState() const { forteWidgetUrl } = useEnvironmentContext() const [isSuccess, setIsSuccess] = useState(false) @@ -56,6 +59,34 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => } }, [widgetInitialized, fortePaymentData]) + const trackSuccessEvent = () => { + const creditCardCheckout = fortePaymentData?.creditCardCheckout + + if (!creditCardCheckout || !analytics) { + return + } + + analytics?.track({ + event: 'SEND_TRANSACTION_REQUEST', + props: { + ...creditCardCheckout.supplementaryAnalyticsInfo, + type: 'credit_card', + provider: 'forte', + source: EVENT_SOURCE, + chainId: String(creditCardCheckout.chainId), + listedCurrency: creditCardCheckout.currencyAddress, + purchasedCurrency: creditCardCheckout.currencyAddress, + origin: window.location.origin, + from: creditCardCheckout.recipientAddress, + to: creditCardCheckout.contractAddress, + item_ids: JSON.stringify([creditCardCheckout.nftId]), + item_quantities: JSON.stringify([JSON.stringify([creditCardCheckout.nftQuantity])]), + txHash: 'unavailable', + paymentIntentId: fortePaymentData?.paymentIntentId || 'unavailable' + } + }) + } + useEffect(() => { let interval: NodeJS.Timeout | undefined let eventFortePaymentsWidgetClosedListener: (e: Event) => void @@ -77,12 +108,14 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => eventFortePaymentsBuyNftMintSuccessListener = (e: Event) => { fortePaymentData?.creditCardCheckout?.forteConfig?.onFortePaymentsBuyNftMintSuccess?.(e) fortePaymentData.creditCardCheckout?.onClose?.() + trackSuccessEvent() setIsSuccess(true) } eventFortePaymentsBuyNftSuccessListener = (e: Event) => { fortePaymentData?.creditCardCheckout?.forteConfig?.onFortePaymentsBuyNftSuccess?.(e) fortePaymentData.creditCardCheckout?.onClose?.() + trackSuccessEvent() setIsSuccess(true) } From 57a44ceffd2cdb4b200a1a676518f0e965d9a869 Mon Sep 17 00:00:00 2001 From: samuelea Date: Mon, 20 Oct 2025 21:41:50 -0400 Subject: [PATCH 2/7] improved event tracking logic --- .../ForteController.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx index ed1b13eeb..434ffdc44 100644 --- a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx +++ b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx @@ -108,15 +108,21 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => eventFortePaymentsBuyNftMintSuccessListener = (e: Event) => { fortePaymentData?.creditCardCheckout?.forteConfig?.onFortePaymentsBuyNftMintSuccess?.(e) fortePaymentData.creditCardCheckout?.onClose?.() - trackSuccessEvent() - setIsSuccess(true) + if (!isSuccess) { + fortePaymentData.creditCardCheckout?.onSuccess?.() + trackSuccessEvent() + setIsSuccess(true) + } } eventFortePaymentsBuyNftSuccessListener = (e: Event) => { fortePaymentData?.creditCardCheckout?.forteConfig?.onFortePaymentsBuyNftSuccess?.(e) fortePaymentData.creditCardCheckout?.onClose?.() - trackSuccessEvent() - setIsSuccess(true) + if (!isSuccess) { + fortePaymentData.creditCardCheckout?.onSuccess?.() + trackSuccessEvent() + setIsSuccess(true) + } } // Note: these events are mutually exclusive. ie they won't trigger at the same time @@ -166,8 +172,13 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => paymentIntentId: fortePaymentData.paymentIntentId }) + // The success events are only triggered when the TX is both successful and that + // the widget is closed in a success state. A seperate payment status check is + // performed to cover the case the user closes without a success state. + if (status === 'Approved' && !isSuccess) { fortePaymentData.creditCardCheckout?.onSuccess?.() + trackSuccessEvent() setIsSuccess(true) } From fd06ffd343be0f8505bcfd1a77bd74307e8f4e42 Mon Sep 17 00:00:00 2001 From: samuelea Date: Mon, 20 Oct 2025 21:44:57 -0400 Subject: [PATCH 3/7] simplified logix related to onSuccess event and tracking --- .../SequenceCheckoutProvider/ForteController.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx index 434ffdc44..dcaac6248 100644 --- a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx +++ b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx @@ -108,21 +108,11 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => eventFortePaymentsBuyNftMintSuccessListener = (e: Event) => { fortePaymentData?.creditCardCheckout?.forteConfig?.onFortePaymentsBuyNftMintSuccess?.(e) fortePaymentData.creditCardCheckout?.onClose?.() - if (!isSuccess) { - fortePaymentData.creditCardCheckout?.onSuccess?.() - trackSuccessEvent() - setIsSuccess(true) - } } eventFortePaymentsBuyNftSuccessListener = (e: Event) => { fortePaymentData?.creditCardCheckout?.forteConfig?.onFortePaymentsBuyNftSuccess?.(e) fortePaymentData.creditCardCheckout?.onClose?.() - if (!isSuccess) { - fortePaymentData.creditCardCheckout?.onSuccess?.() - trackSuccessEvent() - setIsSuccess(true) - } } // Note: these events are mutually exclusive. ie they won't trigger at the same time @@ -172,10 +162,6 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => paymentIntentId: fortePaymentData.paymentIntentId }) - // The success events are only triggered when the TX is both successful and that - // the widget is closed in a success state. A seperate payment status check is - // performed to cover the case the user closes without a success state. - if (status === 'Approved' && !isSuccess) { fortePaymentData.creditCardCheckout?.onSuccess?.() trackSuccessEvent() From a4cc659a753bd1178680f70149e2b4578b93d6f7 Mon Sep 17 00:00:00 2001 From: samuelea Date: Tue, 21 Oct 2025 14:45:56 -0400 Subject: [PATCH 4/7] set analytics options explicitly to true --- .../SequenceConnectProvider/SequenceConnectProvider.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx b/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx index b50ce1201..24aa22179 100644 --- a/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx +++ b/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx @@ -103,7 +103,10 @@ export const SequenceConnectProvider = (props: SequenceConnectProviderProps) => const googleClientId: string = (googleWaasConnector as any)?.params?.googleClientId || '' const setupAnalytics = (projectAccessKey: string) => { - const s = sequence.initWallet(projectAccessKey) + const s = sequence.initWallet(projectAccessKey, { + analytics: true + }) + const sequenceAnalytics = s.client.analytics if (sequenceAnalytics) { From 5ba622be1576f46f8e3de3f9f3741ecb0df86c82 Mon Sep 17 00:00:00 2001 From: samuelea Date: Thu, 23 Oct 2025 11:54:02 -0400 Subject: [PATCH 5/7] undefined analytics object fix --- .../SequenceConnectProvider.tsx | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx b/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx index 24aa22179..c556d1dcf 100644 --- a/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx +++ b/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx @@ -4,7 +4,7 @@ import { sequence } from '0xsequence' import { Button, Card, Modal, ModalPrimitive, Text, type Theme } from '@0xsequence/design-system' import { SequenceHooksProvider } from '@0xsequence/hooks' import { ChainId } from '@0xsequence/network' -import { SequenceClient } from '@0xsequence/provider' +import { SequenceClient, setupAnalytics, type Analytics } from '@0xsequence/provider' import { GoogleOAuthProvider } from '@react-oauth/google' import { AnimatePresence } from 'motion/react' import React, { useEffect, useState } from 'react' @@ -102,28 +102,23 @@ export const SequenceConnectProvider = (props: SequenceConnectProviderProps) => ) as ExtendedConnector | undefined const googleClientId: string = (googleWaasConnector as any)?.params?.googleClientId || '' - const setupAnalytics = (projectAccessKey: string) => { - const s = sequence.initWallet(projectAccessKey, { - analytics: true - }) - - const sequenceAnalytics = s.client.analytics + const getAnalyticsClient = (projectAccessKey: string) => { + // @ts-ignore-next-line + const sequenceAnalytics = setupAnalytics(projectAccessKey) as Analytics - if (sequenceAnalytics) { - type TrackArgs = Parameters - const originalTrack = sequenceAnalytics.track.bind(sequenceAnalytics) + type TrackArgs = Parameters + const originalTrack = sequenceAnalytics.track.bind(sequenceAnalytics) - sequenceAnalytics.track = (...args: TrackArgs) => { - const [event] = args - if (event && typeof event === 'object' && 'props' in event) { - event.props = { - ...event.props, - sdkType: 'sequence web sdk', - version: WEB_SDK_VERSION - } + sequenceAnalytics.track = (...args: TrackArgs) => { + const [event] = args + if (event && typeof event === 'object' && 'props' in event) { + event.props = { + ...event.props, + sdkType: 'sequence web sdk', + version: WEB_SDK_VERSION } - return originalTrack?.(...args) } + return originalTrack?.(...args) } setAnalytics(sequenceAnalytics) } @@ -141,7 +136,7 @@ export const SequenceConnectProvider = (props: SequenceConnectProviderProps) => useEffect(() => { if (!disableAnalytics) { - setupAnalytics(config.projectAccessKey) + getAnalyticsClient(config.projectAccessKey) } }, []) From c8425662db9ff7c56f61d84c81f6d6b6a938e252 Mon Sep 17 00:00:00 2001 From: samuelea Date: Thu, 23 Oct 2025 11:54:51 -0400 Subject: [PATCH 6/7] imports cleanup --- .../SequenceConnectProvider/SequenceConnectProvider.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx b/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx index c556d1dcf..7690c558a 100644 --- a/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx +++ b/packages/connect/src/components/SequenceConnectProvider/SequenceConnectProvider.tsx @@ -1,6 +1,5 @@ 'use client' -import { sequence } from '0xsequence' import { Button, Card, Modal, ModalPrimitive, Text, type Theme } from '@0xsequence/design-system' import { SequenceHooksProvider } from '@0xsequence/hooks' import { ChainId } from '@0xsequence/network' From 5beef339d24ac6b0f8232e85168b6b81a388861c Mon Sep 17 00:00:00 2001 From: samuelea Date: Thu, 23 Oct 2025 12:17:37 -0400 Subject: [PATCH 7/7] purchase currency symbol field --- .../components/SequenceCheckoutProvider/ForteController.tsx | 2 +- packages/checkout/src/views/PendingCreditCardTransaction.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx index dcaac6248..1c5cb2bc9 100644 --- a/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx +++ b/packages/checkout/src/components/SequenceCheckoutProvider/ForteController.tsx @@ -74,7 +74,7 @@ export const ForteController = ({ children }: { children: React.ReactNode }) => provider: 'forte', source: EVENT_SOURCE, chainId: String(creditCardCheckout.chainId), - listedCurrency: creditCardCheckout.currencyAddress, + purchasedCurrencySymbol: creditCardCheckout.currencySymbol, purchasedCurrency: creditCardCheckout.currencyAddress, origin: window.location.origin, from: creditCardCheckout.recipientAddress, diff --git a/packages/checkout/src/views/PendingCreditCardTransaction.tsx b/packages/checkout/src/views/PendingCreditCardTransaction.tsx index 3f806af06..429f23bb1 100644 --- a/packages/checkout/src/views/PendingCreditCardTransaction.tsx +++ b/packages/checkout/src/views/PendingCreditCardTransaction.tsx @@ -151,7 +151,7 @@ export const PendingCreditCardTransactionTransak = ({ skipOnCloseCallback }: Pen provider: 'transak', source: EVENT_SOURCE, chainId: String(creditCardCheckout.chainId), - listedCurrency: creditCardCheckout.currencyAddress, + purchasedCurrencySymbol: creditCardCheckout.currencySymbol, purchasedCurrency: creditCardCheckout.currencyAddress, origin: window.location.origin, from: creditCardCheckout.recipientAddress, @@ -330,7 +330,7 @@ export const PendingCreditCardTransactionSardine = ({ skipOnCloseCallback }: Pen provider: 'sardine', source: EVENT_SOURCE, chainId: String(creditCardCheckout.chainId), - listedCurrency: creditCardCheckout.currencyAddress, + purchasedCurrencySymbol: creditCardCheckout.currencySymbol, purchasedCurrency: creditCardCheckout.currencyAddress, origin: window.location.origin, from: creditCardCheckout.recipientAddress,