-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Analytics Architecture Refactor: GA4 to GTM Migration #5360
base: develop
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
2 Skipped Deployments
|
/apps/cow-fi not building - but is fixed in PR #5363 |
@fairlighteth amazing initiative!
The main idea is to keep the GTM as independent as possible. https://chatgpt.com/share/67a0782b-6020-8013-88a0-73436c6b6a33 |
* @param gtmId - Optional GTM container ID | ||
* @returns CowAnalytics instance backed by GTM | ||
*/ | ||
export function initGtm(gtmId: string = DEFAULT_GTM_ID): CowAnalytics { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function creates a new instance of CowAnalyticsGtm
on each call and inserts the GTM script in DOM. I see you call the function in many components in cow-fi. We should not do that.
This function should insert the script and instantiate CowAnalyticsGtm only once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this. I've refactored the initGtm
function to use a singleton pattern that ensures GTM is only initialized once, regardless of how many times it's called. The script injection now happens only on first initialization, and subsequent calls will return the existing instance. I've also added proper error handling for edge cases like attempting to initialize with different GTM IDs.
@@ -22,6 +33,8 @@ export const ThemeProvider = ({ children }: PropsWithChildren) => { | |||
// Compute the app colour pallette using the passed in themeMode | |||
...themePalette, | |||
...fontPalette, | |||
// Add widget mode flags | |||
...widgetMode, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no widget mode in explorer, why do we add the value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
@@ -63,9 +64,25 @@ interface TransactionSettingsProps { | |||
deadlineState: StatefulValue<number> | |||
} | |||
|
|||
type SlippageAnalyticsAction = 'Default' | 'Custom' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types are identical, might they be generalized? Smth like TxSettingAction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
* CowSwap-specific analytics categories | ||
* Extends the base Category enum with CowSwap-specific values | ||
*/ | ||
export enum CowSwapCategory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same suggestion, rename to AnalyticsCategory
or CowSwapAnalyticsCategory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed (CowSwapAnalyticsCategory
)
} | ||
|
||
// Type assertion to ensure CowSwapCategory extends AnalyticsCategory | ||
const _assertType: AnalyticsCategory = CowSwapCategory.SERVICE_WORKER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assertion looks redundant. The value implicitly inherited from AnalyticsCategory: SERVICE_WORKER = Category.SERVICE_WORKER,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
@@ -94,7 +98,9 @@ export default class ErrorBoundary extends React.Component<PropsWithChildren, Er | |||
} | |||
|
|||
componentDidCatch(error: Error, errorInfo: ErrorInfo) { | |||
cowAnalytics.sendError(error, errorInfo.toString()) | |||
if (this.props.onError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick, might be shorter:
this.props.onError?.(error, errorInfo)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
const { chainId, account } = useWalletInfo() | ||
const { walletName } = useWalletDetails() | ||
const cowAnalytics = useCowAnalytics() | ||
const pixel = initPixelAnalytics() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pixel
is a static value and must be outside of the component function, otherwise it will cause unwanted rerenders.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
/** | ||
* Creates a debounced function that sends analytics events for trade amount changes | ||
*/ | ||
export function createDebouncedTradeAmountAnalytics(cowAnalytics: CowAnalytics) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function probably should be a part of modules/trade
since it's logically connect only to trade widgets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
@@ -18,12 +18,29 @@ import { useCloseReceiptModal } from 'modules/ordersTable/containers/OrdersRecei | |||
import { TradeConfirmActions } from 'modules/trade/hooks/useTradeConfirmActions' | |||
import { useAlternativeOrder, useHideAlternativeOrderModal } from 'modules/trade/state/alternativeOrder' | |||
import { getSwapErrorMessage } from 'modules/trade/utils/swapErrorHelper' | |||
import { useTradeFlowAnalytics } from 'modules/trade/utils/tradeFlowAnalytics' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be import { useTradeFlowAnalytics } from 'modules/trade'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
TABLE_POSITION = 'Orders Table Position', | ||
} | ||
|
||
export function useLimitOrderSettingsAnalytics() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a hook, the file name should have the same name and the file should be in hooks
directory instead of utils
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
[connectionType, ensName, pendingCount], | ||
) | ||
|
||
const handleConnect = useCallback(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks redundant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
Warning Rate limit exceeded@fairlighteth has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 34 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (145)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🔭 Outside diff range comments (2)
apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx (1)
78-144
: Remove duplicate analytics eventThe same event is sent twice when importing a list - once in
addCustomTokenLists
and again inimportListAndBack
.const addCustomTokenLists = useAddList((source) => { cowAnalytics.sendEvent({ category: CowSwapCategory.LIST, action: 'Add List Success', label: source, }) }) const importListAndBack = (list: ListState) => { try { addCustomTokenLists(list) - cowAnalytics.sendEvent({ - category: CowSwapCategory.LIST, - action: 'Add List Success', - label: list.source, - }) } catch (error) { onDismiss() onTokenListAddingError(error) } updateSelectTokenWidget({ listToImport: undefined }) }apps/cow-fi/app/(main)/cow-protocol/page.tsx (1)
4-11
: Fix import order.The imports need to be reordered according to the project's conventions.
Apply this diff to fix the import order:
-import { Color, ProductLogo, ProductVariant } from '@cowprotocol/ui' -import IMG_ICON_CROWN_COW from '@cowprotocol/assets/images/icon-crown-cow.svg' -import IMG_ICON_BULB_COW from '@cowprotocol/assets/images/icon-bulb-cow.svg' -import IMG_ICON_BUILD_WITH_COW from '@cowprotocol/assets/images/icon-build-with-cow.svg' -import IMG_ICON_SECURE from '@cowprotocol/assets/images/icon-secure.svg' -import IMG_ICON_OWL from '@cowprotocol/assets/images/icon-owl.svg' -import IMG_ICON_GHOST from '@cowprotocol/assets/images/icon-ghost.svg' -import IMG_LOGO_SAFE from '@cowprotocol/assets/images/icon-logo-safe.svg' +import { initGtm } from '@cowprotocol/analytics' +import { Color, ProductLogo, ProductVariant } from '@cowprotocol/ui' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' + +import IMG_ICON_CROWN_COW from '@cowprotocol/assets/images/icon-crown-cow.svg' +import IMG_ICON_BULB_COW from '@cowprotocol/assets/images/icon-bulb-cow.svg' +import IMG_ICON_BUILD_WITH_COW from '@cowprotocol/assets/images/icon-build-with-cow.svg' +import IMG_ICON_SECURE from '@cowprotocol/assets/images/icon-secure.svg' +import IMG_ICON_OWL from '@cowprotocol/assets/images/icon-owl.svg' +import IMG_ICON_GHOST from '@cowprotocol/assets/images/icon-ghost.svg' +import IMG_LOGO_SAFE from '@cowprotocol/assets/images/icon-logo-safe.svg'🧰 Tools
🪛 ESLint
[error] 4-4:
@cowprotocol/assets/images/icon-crown-cow.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 5-5:
@cowprotocol/assets/images/icon-bulb-cow.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 6-6:
@cowprotocol/assets/images/icon-build-with-cow.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 7-7:
@cowprotocol/assets/images/icon-secure.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 8-8:
@cowprotocol/assets/images/icon-owl.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 9-9:
@cowprotocol/assets/images/icon-ghost.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 10-10:
@cowprotocol/assets/images/icon-logo-safe.svg
import should occur before import of@cowprotocol/ui
(import/order)
[error] 11-11:
@cowprotocol/assets/images/icon-logo-lido.svg
import should occur before import of@cowprotocol/ui
(import/order)
♻️ Duplicate comments (2)
apps/explorer/src/theme/ThemeProvider.tsx (1)
15-22
: 🛠️ Refactor suggestionRemove unnecessary widget mode in Explorer
MOO! 🐮 As previously noted, Explorer doesn't need widget mode functionality.
-// These values are static and don't change during runtime -const isWidget = isInjectedWidget() -const widgetMode = { - isWidget, - isIframe: isIframe(), - // TODO: isInjectedWidgetMode is deprecated, use isWidget instead - // This alias is kept for backward compatibility with styled components - isInjectedWidgetMode: isWidget, -}apps/cow-fi/components/ArticlesPageComponents.tsx (1)
23-23
: 🛠️ Refactor suggestionMOOve GTM initialization to use shared hook! 🐮
Similar to AddRpcButton, GTM should be initialized at a higher level using the shared hook.
🧹 Nitpick comments (73)
apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/styled.ts (1)
110-121
: MOOving from p to div: Good choice! 🐮The change from
styled.p
tostyled.div
is a good MOOve! This allows for more flexible content nesting while maintaining the same styling. The component can now properly contain interactive elements like buttons and links, which is more semantic and accessible.Consider adding an aria-label or role="description" for better accessibility:
-export const Description = styled.div<{ center?: boolean; margin?: string }>` +export const Description = styled.div.attrs({ role: 'description' })<{ center?: boolean; margin?: string }>`libs/analytics/src/index.ts (1)
6-8
: Let's optimize our GTM implementation, fellow CoW! 🐮The type exports look great for ensuring type safety. However, based on the PR discussion, we could enhance click tracking.
Consider implementing a phased approach as suggested:
- Use GTM's native "Click trigger" as the primary method (requires adding IDs to elements)
- Fall back to
toGtmEvent
for complex scenariosThis would make our GTM implementation more maintainable and performant.
apps/cowswap-frontend/src/modules/trade/utils/tradeFlowAnalytics.ts (1)
25-66
: Centralized sendTradeAnalytics method.
This is a clean approach, ensuring analytics events are dispatched in one place. The “error” method elegantly handles both user rejections vs. actual errors with numeric codes. Great to see a uniform design for all trade flow events.Consider logging additional context when an error occurs to help debugging further (e.g. adding a bit more context on the
errorMessage
beyond “Error”). But overall, the event structure is coherent.libs/analytics/src/gtm/CowAnalyticsGtm.ts (2)
36-36
: Moo! Watch out for potential performance bottlenecks.Attaching a global click listener may become a bit heavy in certain barn-sized applications. Consider scoping or throttling the event as the app grows, especially if there are many clickable elements.
172-176
: We smell a debug leftover.Remember to remove or gate this console.log call before shipping to production. Console spamming can hamper performance when many events are pushed.
apps/cowswap-frontend/src/modules/application/containers/App/index.tsx (1)
57-72
: Milk your analytics efficiently!You're re-initializing analytics objects on every render. To avoid churn, consider wrapping "cowAnalytics," "pixel," and "webVitals" in a memo or referencing them from a stable context to prevent re-instantiation.
apps/explorer/src/common/analytics/types.ts (1)
6-9
: MOOving in the right direction with analytics categories! 🐮The ExplorerCategory enum is well-structured and properly documented. As we graze through more analytics needs, we can easily add more categories here.
Consider adding categories for other explorer-specific events like
TRANSACTION_DETAILS
,BLOCK_DETAILS
, etc., as we expand our analytics pasture.libs/analytics/src/context/CowAnalyticsContext.tsx (1)
24-26
: Let's make our error MOO-ssage more helpful! 🐮The error message could be more descriptive to help developers understand where to add the provider.
- throw new Error('required CowAnalyticsProvider') + throw new Error('CowAnalyticsProvider not found in component tree. Wrap your component with CowAnalyticsProvider to use analytics.')apps/cowswap-frontend/src/legacy/state/price/middleware.ts (1)
14-14
: MOOve the analytics initialization outside the middlewareAs a CoW who loves clean code, I suggest moving the GTM initialization to a central location. The middleware should receive the analytics instance as a parameter rather than initializing it internally.
-const cowAnalytics = initGtm() export const priceMiddleware: Middleware<Record<string, unknown>, AppState> = ( + analytics: ReturnType<typeof initGtm>, ) => (store) => (next) => (action) => {apps/cow-fi/components/ArticlesList.tsx (1)
2-6
: MOOve these imports into proper groupsLet's organize these imports better:
import React from 'react' + import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' import { LinkItem, LinkColumn } from '@/styles/styled' import { Article } from 'services/cms' +import { CowFiCategory } from 'src/common/analytics/types'Also, I noticed we're not using
toCowFiGtmEvent
, so we can remove it from imports.🧰 Tools
🪛 ESLint
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 3-3: There should be at least one empty line between import groups
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 5-5:
services/cms
import should occur before import ofsrc/common/analytics/types
(import/order)
apps/cow-fi/src/common/analytics/types.ts (1)
37-42
: Type casting could be improvedThe type casting using
unknown
could be made more type-safe:export function toCowFiGtmEvent(event: Omit<CowFiGtmEvent, 'category'> & { category: CowFiCategory }): string { return toGtmEvent({ ...event, - category: event.category as unknown as AnalyticsCategory, + category: event.category as AnalyticsCategory, } as GtmEvent) }apps/cow-fi/components/NotFoundPageComponent.tsx (1)
5-6
: Clean up importsLet's remove the unused import and organize them:
import { ArticleContent, ArticleMainTitle, BodyContent, ContainerCard, PageWrapper } from '@/styles/styled' import { Link } from '@/components/Link' + import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { CowFiCategory } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 5-5: There should be at least one empty line between import groups
(import/order)
[error] 6-6: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx (1)
9-9
: MOOving in the right direction with analytics migration! 🐮The changes look good, replacing direct analytics calls with the new GTM-based hook. The implementation is clean and follows the new analytics architecture.
Consider adding a data attribute for declarative click tracking as an alternative:
<SettingsButton + data-gtm-click="limit-order-settings" onClick={() => analytics.openSettings()}>
Also applies to: 14-14, 19-19
libs/analytics/src/types.ts (1)
9-14
: MOO-ve these categories to app-specific files! 🐮While the Category enum provides backward compatibility, these UI categories should ideally live in the respective applications that use them. This would maintain better separation of concerns.
Consider moving these categories to app-specific files and using string literal types here instead:
export type Category = 'Service Worker' | 'Footer' | 'External Link'apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx (1)
43-46
: Let's make this event more MOO-ningful! 🐮While the analytics integration is correct, we could make the event more descriptive and track additional user interactions.
Consider these enhancements:
cowAnalytics.sendEvent({ category: CowSwapCategory.GAMES, - action: 'Playing CoW Runner game', + action: 'Game Started', + label: 'CoW Runner' })Also, consider tracking game-specific events like:
- Game Over
- High Score
- Power-up Collection
libs/analytics/src/gtm/types.ts (2)
16-35
: Enhance type guard with exhaustive property checkingMOOving through the code, I noticed we could make the type guard even more robust! 🐮
export function isValidGtmClickEvent(data: unknown): data is GtmClickEvent { if (typeof data !== 'object' || data === null) return false const event = data as Record<string, unknown> + // Get all keys from the event object + const eventKeys = Object.keys(event) + + // Define allowed keys + const allowedKeys = [ + 'category', + 'action', + 'label', + 'value', + 'orderId', + 'orderType', + 'tokenSymbol', + 'chainId', + 'context' + ] + + // Check for unexpected properties + if (eventKeys.some(key => !allowedKeys.includes(key))) return false // Required fields if (typeof event.category !== 'string' || typeof event.action !== 'string') { return false } // Optional fields if (event.label !== undefined && typeof event.label !== 'string') return false if (event.value !== undefined && typeof event.value !== 'number') return false if (event.orderId !== undefined && typeof event.orderId !== 'string') return false if (event.orderType !== undefined && typeof event.orderType !== 'string') return false if (event.tokenSymbol !== undefined && typeof event.tokenSymbol !== 'string') return false if (event.chainId !== undefined && typeof event.chainId !== 'number') return false return true }
37-40
: Add type validation in toGtmEvent helperLet's ensure our events are always valid before they're stringified! 🎯
export function toGtmEvent(event: Partial<GtmClickEvent>): string { + // Validate required fields + if (!event.category || !event.action) { + throw new Error('GTM events require category and action') + } return JSON.stringify(event) }apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx (1)
24-33
: Add aria-label for better accessibilityHey there! 🐮 Let's make our link more accessible for screen readers!
<HashLink target="_blank" to="/faq/limit-order#how-do-fees-work" + aria-label="Learn more about limit order fees" data-click-event={toCowSwapGtmEvent({ category: CowSwapCategory.TRADE, action: 'Click limit order fees FAQ link', })} > Learn more </HashLink>
apps/cow-fi/app/providers.tsx (1)
6-6
: Consider moving GTM initialization inside the componentAs a fellow CoW 🐮, I suggest moving the GTM initialization inside the component to avoid potential SSR issues. This ensures GTM is only initialized when the component mounts.
-const cowAnalytics = initGtm() export function Providers({ children }: { children: React.ReactNode }) { + const cowAnalytics = initGtm() return ( // ... rest of the codeAlso applies to: 14-14
🧰 Tools
🪛 ESLint
[error] 6-6: There should be at least one empty line between import groups
(import/order)
[error] 6-6:
@cowprotocol/analytics
import should occur before import of../services/uniswap-price/apollo-client
(import/order)
apps/cowswap-frontend/src/modules/limitOrders/utils/limitOrderSettingsAnalytics.ts (2)
26-31
: Add type safety to custom labelsLet's make this more type-safe by using a tuple type for customLabels:
- const sendToggleAnalytics = (action: LimitOrderSettingsAction, enable: boolean, customLabels?: [string, string]) => { + const sendToggleAnalytics = ( + action: LimitOrderSettingsAction, + enable: boolean, + customLabels?: readonly [enabledLabel: string, disabledLabel: string] + ) => {
43-45
: Add type safety to position parametersConsider creating an enum or union type for the position values:
+type PricePosition = 'left' | 'right' | 'top' | 'bottom' - changeLimitPricePosition(oldPosition: string, newPosition: string) { + changeLimitPricePosition(oldPosition: PricePosition, newPosition: PricePosition) {apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwapOrEthFlow.ts (1)
39-45
: Grazing on some good code here! 🌿The refactoring to use object parameters is a good improvement. However, we could enhance type safety by defining an interface for the parameters.
Consider adding a type definition:
interface EthFlowParams { tradeContext: SwapFlowContext ethFlowContext: EthFlowContext priceImpactParams: PriceImpactParams confirmPriceImpactWithoutFee: ConfirmPriceImpactWithoutFee analytics: TradeFlowAnalytics }apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx (1)
30-39
: MOOve analytics event to a shared constants file 🐮Consider extracting the analytics event category and action to a shared constants file to maintain consistency across the application.
+ // In common/analytics/constants.ts + export const TWAP_ANALYTICS = { + CATEGORY: CowSwapCategory.TWAP, + ACTIONS: { + CONVERSION: 'Conversion', + }, + } - const twapConversionAnalytics = useCallback( - (status: string, fallbackHandlerIsNotSet: boolean) => { - cowAnalytics.sendEvent({ - category: CowSwapCategory.TWAP, - action: 'Conversion', - label: `${status}|${fallbackHandlerIsNotSet ? 'no-handler' : 'handler-set'}`, - }) - }, - [cowAnalytics], - ) + const twapConversionAnalytics = useCallback( + (status: string, fallbackHandlerIsNotSet: boolean) => { + cowAnalytics.sendEvent({ + category: TWAP_ANALYTICS.CATEGORY, + action: TWAP_ANALYTICS.ACTIONS.CONVERSION, + label: `${status}|${fallbackHandlerIsNotSet ? 'no-handler' : 'handler-set'}`, + }) + }, + [cowAnalytics], + )apps/cow-fi/app/(main)/legal/page.tsx (2)
3-6
: Fix import ordering 🐮The imports need to be grouped and ordered correctly according to the static analysis hints.
+ import { initGtm } from '@cowprotocol/analytics' import { Color } from '@cowprotocol/ui' - import { initGtm } from '@cowprotocol/analytics' - import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' import styled from 'styled-components/macro' + import { CowFiCategory } from 'src/common/analytics/types' import { Link } from '@/components/Link'🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 6-6: There should be at least one empty line between import groups
(import/order)
10-10
: MOOve analytics initialization to app level 🐮The analytics initialization should be moved to a higher level (e.g., app providers) to ensure a single instance is shared across components.
apps/widget-configurator/src/main.tsx (1)
19-21
: Add error handling for analytics initialization 🐮Consider adding error handling for the analytics initialization to gracefully handle potential failures.
// Initialize analytics instance -export const cowAnalytics = initGtm() +export const cowAnalytics = (() => { + try { + return initGtm() + } catch (error) { + console.warn('Failed to initialize analytics:', error) + // Return a no-op implementation + return { + sendEvent: () => {}, + // ... other required methods + } + } +})()apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx (1)
43-49
: Excellent implementation of device-specific analytics tracking! 🎯The differentiation between mobile and desktop interactions will provide valuable insights into user behavior across devices. The implementation is clean and follows best practices.
Consider adding analytics for the settings toggle action as well for complete coverage.
<ArrowLeft onClick={toggleSettingsOpen} data-click-event={toCowSwapGtmEvent({ category: CowSwapCategory.NOTIFICATIONS, - action: 'Close notification settings', + action: 'Toggle notification settings', + label: isMobile ? 'mobile' : 'desktop', })} />Also applies to: 59-77
apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts (1)
67-68
: Consider enhancing error analyticsWhile we're capturing error codes, we could provide more detailed error categorization for better debugging.
-approvalAnalytics('Error', symbol, errorCode) +approvalAnalytics('Error', symbol, errorCode, { + errorType: error?.name || 'Unknown', + errorMessage: errorToString(error).substring(0, 100) // Truncate long messages +})apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts (1)
41-41
: Consider adding type safety for analytics parametersWhile the implementation works, we could enhance type safety for the analytics parameters.
-debouncedTradeAmountAnalytics([field, Number(typedValue)]) +debouncedTradeAmountAnalytics({ + field, + amount: Number(typedValue), + currency: field === Field.INPUT ? inputCurrency?.symbol : outputCurrency?.symbol +})apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx (1)
70-75
: MOOve towards type safety with event names! 🎯Consider extracting the event action string into a type-safe constant to prevent typos and ensure consistency.
+const SAFE_HANDLER_EVENTS = { + MODIFY_CHECKBOX: 'Modify safe handler checkbox', +} as const; data-click-event={toCowSwapGtmEvent({ category: CowSwapCategory.TWAP, - action: 'Modify safe handler checkbox', + action: SAFE_HANDLER_EVENTS.MODIFY_CHECKBOX, label: isFallbackHandlerSetupAccepted ? 'enabled' : 'disabled', })}apps/cowswap-frontend/src/legacy/components/Header/AccountElement/index.tsx (1)
22-28
: MOOve this function inside useCallback! 🐄The event data creation function could be memoized to prevent unnecessary re-renders.
-function createNotificationClickEventData(event: string): string { +const createNotificationClickEventData = useCallback((event: string): string => { return toCowSwapGtmEvent({ category: CowSwapCategory.NOTIFICATIONS, action: event, }) -} +}, [])apps/cowswap-frontend/src/modules/tokensList/pure/ListItem/index.tsx (1)
57-62
: MOOve repeated event creation logic to a helper! 🎯Let's extract the repeated event creation logic into a reusable helper function to keep our code DRY.
+const createListEvent = (action: string, label: string) => + toCowSwapGtmEvent({ + category: CowSwapCategory.LIST, + action, + label, + }) -data-click-event={toCowSwapGtmEvent({ - category: CowSwapCategory.LIST, - action: 'View List', - label: list.source, -})} +data-click-event={createListEvent('View List', list.source)}Also applies to: 69-74, 85-90
apps/cowswap-frontend/src/modules/tradeFlow/hooks/useHandleSwap.ts (1)
7-7
: MOOving in the right direction! Analytics integration looks good.The analytics integration is well-structured and consistent. The analytics object is properly passed through to all flow functions and added to the dependencies array.
Consider adding a comment explaining the analytics parameter's purpose in the flow functions for better maintainability.
Also applies to: 26-26, 48-48, 60-60, 65-65, 81-81
apps/cow-fi/components/CategoryLinks.tsx (1)
3-5
: Let's keep our imports MOOving in order!The import statements need to be reorganized according to our style guide:
import React from 'react' import styled from 'styled-components/macro' +import Link from 'next/link' + import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' import { Color, Media } from '@cowprotocol/ui' -import Link from 'next/link' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'Also applies to: 8-8
🧰 Tools
🪛 ESLint
[error] 3-3: There should be at least one empty line between import groups
(import/order)
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4:
src/common/analytics/types
import should occur after import ofnext/link
(import/order)
[error] 4-4: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 5-5: There should be at least one empty line between import groups
(import/order)
apps/cowswap-frontend/src/modules/wallet/containers/WatchAssetInWallet/index.tsx (1)
53-68
: Excellent tracking of wallet interactions!The implementation provides comprehensive event tracking for both successful and failed attempts to watch assets. The click tracking via data attributes is a nice touch.
Consider including the error message in the failure event label for better debugging:
- label: `Failed: ${token.symbol}`, + label: `Failed: ${token.symbol} - ${error.message}`,Also applies to: 85-89
apps/cow-fi/components/TokensList/index.tsx (1)
6-6
: Moo! Fix import ordering.Add an empty line between import groups to maintain consistency.
import { TokenInfo } from 'types' + import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
🧰 Tools
🪛 ESLint
[error] 6-6: There should be at least one empty line between import groups
(import/order)
apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx (1)
41-45
: Moo! Consider standardizing event tracking approach! 🤔While the implementation works, we're using
sendEvent
here butdata-click-event
elsewhere. Let's standardize ondata-click-event
for consistency.- sendEvent({ - category: CowSwapCategory.TWAP, - action: 'Apply custom deadline', - label: `${hoursValue}h ${minutesValue}m`, - }) + // Add data-click-event to the Apply button insteadapps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx (1)
67-76
: Hay there! Consider adding error tracking.While the import list implementation looks good, we should track failed imports as well.
importList={() => { if (listToImport) { addListImport(listToImport) + cowAnalytics.sendEvent({ + category: CowSwapCategory.LIST, + action: 'Import List Success', + label: listToImport.source, + }) + } else { + cowAnalytics.sendEvent({ + category: CowSwapCategory.LIST, + action: 'Import List Failed', + label: 'No list to import', + }) } }}apps/cow-fi/components/TopicsPageComponent.tsx (1)
16-17
: Let's keep our imports as organized as a well-managed herd! 🐄The import ordering needs to be fixed according to the project's style guide.
import { ArrowButton } from '@/components/ArrowButton' + import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' import { CmsImage, Color, Font, Media } from '@cowprotocol/ui' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 16-16: There should be at least one empty line between import groups
(import/order)
[error] 17-17: There should be at least one empty line between import groups
(import/order)
[error] 17-17:
src/common/analytics/types
import should occur after import of@cowprotocol/ui
(import/order)
[error] 17-17: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
libs/analytics/src/hooks/useAnalyticsReporter.ts (1)
68-74
: MOO-ve service worker tracking to be more descriptive 🐮While the implementation works, we could make the service worker status tracking more informative by including additional metadata.
Consider this enhancement:
- const action = installed ? (hit ? 'Cache hit' : 'Cache miss') : 'Not installed' + const action = installed + ? `Cache ${hit ? 'hit' : 'miss'} (SW version: ${window.navigator.serviceWorker.controller?.scriptURL || 'unknown'})` + : 'Not installed'apps/cowswap-frontend/src/cosmos.decorator.tsx (1)
92-93
: Add MOO-re context to the initialization comment 🐮While the GTM initialization works correctly, let's make the comment more descriptive for future developers.
Consider this enhancement:
-// Initialize analytics for cosmos +// Initialize Google Tag Manager (GTM) for cosmos playground +// This enables event tracking in the component playground environmentapps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx (1)
3-3
: MOOve imports to follow consistent order! 🐮Let's organize these imports to follow our standard pattern:
- External dependencies
- Internal utilities
- Local components/types
import { useCallback } from 'react' + +import { useCowAnalytics } from '@cowprotocol/analytics' import { isInjectedWidget } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' import { useTokensByAddressMap } from '@cowprotocol/tokens' import { ClosableBanner } from '@cowprotocol/ui' import { useIsSmartContractWallet, useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' -import { useCowAnalytics } from '@cowprotocol/analytics' import { useIsDarkMode } from 'legacy/state/user/hooks' +import { CowSwapCategory, toCowSwapGtmEvent } from 'common/analytics/types' import { useTradeNavigate } from 'modules/trade' import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState' import { useYieldRawState } from 'modules/yield' import { useVampireAttack, useVampireAttackFirstTarget } from 'modules/yield/shared' - -import { CowSwapCategory, toCowSwapGtmEvent } from 'common/analytics/types'Also applies to: 18-18
libs/ui/src/theme/baseTheme.tsx (1)
61-61
: Add color documentation for future reference! 🎨Consider adding comments to explain the use cases for these new colors.
// ****** backgrounds ****** -bg3: darkMode ? '#1a3c6b' : '#D0E3EC', +// Used for secondary container backgrounds +bg3: darkMode ? '#1a3c6b' : '#D0E3EC', // ****** greys ****** -grey1: darkMode ? '#40587F' : '#8FA3BF', +// Used for secondary text and icons +grey1: darkMode ? '#40587F' : '#8FA3BF',Also applies to: 66-66
apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx (1)
101-103
: MOO-ve to optional chaining for conciseness 🐮As suggested in a previous review, we can make this more concise:
- if (this.props.onError) { - this.props.onError(error, errorInfo) - } + this.props.onError?.(error, errorInfo)apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts (1)
31-37
: Let's make the return type MOO-re precise 🐮The static analysis tool flagged a potential improvement in the return type.
-}: EthFlowParams): Promise<void | boolean> { +}: EthFlowParams): Promise<undefined | boolean> {This makes the return type more explicit since
void
in union types can be confusing.🧰 Tools
🪛 Biome (1.9.4)
[error] 37-37: void is confusing inside a union type.
Unsafe fix: Use undefined instead.
(lint/suspicious/noConfusingVoidType)
apps/cow-fi/lib/hooks/useConnectAndAddToWallet.ts (1)
7-10
: Reorder imports for better organization.Let's keep our imports as organized as a well-managed herd! Move the analytics imports before local imports.
-import { useCallback, useState } from 'react' -import { useConnect } from './useConnect' -import { useDisconnect, useWalletClient } from 'wagmi' -import { handleRpcError } from '@/util/handleRpcError' -import { useAddRpcWithTimeout } from './useAddRpcWithTimeout' -import { AddToWalletState, AddToWalletStateValues } from '../../types/addToWalletState' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { useCallback, useState } from 'react' +import { useDisconnect, useWalletClient } from 'wagmi' + +import { initGtm } from '@cowprotocol/analytics' +import { CowFiCategory } from 'src/common/analytics/types' + +import { handleRpcError } from '@/util/handleRpcError' +import { useConnect } from './useConnect' +import { useAddRpcWithTimeout } from './useAddRpcWithTimeout' +import { AddToWalletState, AddToWalletStateValues } from '../../types/addToWalletState'🧰 Tools
🪛 ESLint
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 7-7:
@cowprotocol/analytics
import should occur before import of./useConnect
(import/order)
[error] 8-8:
src/common/analytics/types
import should occur before import of./useConnect
(import/order)
[error] 8-8: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx (1)
209-209
: Consider making the Twitter message configurable.The Twitter message is currently hardcoded. Consider moving it to a configuration file for easier updates and A/B testing.
apps/explorer/src/explorer/ExplorerApp.tsx (1)
28-31
: Consider memoizing analytics instances.These analytics instances are created at the module level, but for better performance, consider wrapping them in useMemo or moving them inside a context provider to prevent unnecessary re-initialization.
-const cowAnalytics = initGtm() -const pixelAnalytics = initPixelAnalytics() -const webVitalsAnalytics = new WebVitalsAnalytics(cowAnalytics) +const useCowAnalyticsInstances = () => { + const cowAnalytics = useMemo(() => initGtm(), []) + const pixelAnalytics = useMemo(() => initPixelAnalytics(), []) + const webVitalsAnalytics = useMemo(() => new WebVitalsAnalytics(cowAnalytics), [cowAnalytics]) + return { cowAnalytics, pixelAnalytics, webVitalsAnalytics } +}apps/cow-fi/components/TopicPageComponent.tsx (1)
115-150
: Reduce duplication in analytics event tracking.The breadcrumb click events follow the same pattern. Let's extract this into a reusable function.
+const trackBreadcrumbClick = (label: string) => + analytics.sendEvent({ + category: CowFiCategory.KNOWLEDGEBASE, + action: 'Click breadcrumb', + label, + }) -<Link - href="/" - onClick={() => - analytics.sendEvent({ - category: CowFiCategory.KNOWLEDGEBASE, - action: 'Click breadcrumb', - label: 'home', - }) - } -> +<Link + href="/" + onClick={() => trackBreadcrumbClick('home')} +>apps/cow-fi/data/home/const.tsx (1)
28-28
: Maintain consistent analytics initialization pattern.Consider following the same pattern as other components by moving analytics initialization to a hook or context. Also, the click handler could be memoized to prevent unnecessary re-renders.
-const analytics = initGtm() +const useHomeAnalytics = () => { + const analytics = useMemo(() => initGtm(), []) + const trackProductClick = useCallback((event: string) => + analytics.sendEvent({ + category: CowFiCategory.HOME, + action: event, + }), [analytics]) + return { trackProductClick } +} // In component: +const { trackProductClick } = useHomeAnalytics() -onClick={() => - analytics.sendEvent({ - category: CowFiCategory.HOME, - action: topic.linkEvent, - }) -} +onClick={() => trackProductClick(topic.linkEvent)}Also applies to: 148-154
apps/cow-fi/app/(main)/page.tsx (1)
7-8
: Let's get these imports in the right pasture! 🌾While the GTM initialization is correct, the import ordering needs to be fixed according to the project's conventions.
-import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { initGtm } from '@cowprotocol/analytics' + +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'Also applies to: 34-34
🧰 Tools
🪛 ESLint
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 8-8:
src/common/analytics/types
import should occur after import of@cowprotocol/assets/images/icon-grants-carton.svg
(import/order)
[error] 8-8: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts (1)
29-42
: Add error tracking to alternative modal analyticsWhile the success tracking is well implemented, we should also track failed attempts.
function useAlternativeModalAnalytics() { const analytics = useCowAnalytics() return useCallback( - (wasPlaced: boolean) => { + (wasPlaced: boolean, error?: Error) => { analytics.sendEvent({ category: CowSwapCategory.TRADE, - action: 'alternative_modal_completion', + action: error ? 'alternative_modal_error' : 'alternative_modal_completion', label: wasPlaced ? 'placed' : 'not-placed', + error: error?.message, }) }, [analytics], ) }apps/widget-configurator/src/app/embedDialog/index.tsx (1)
99-106
: Add error handling for clipboard operationsThe clipboard operation could fail in some browsers or contexts.
const handleCopyClick = () => { - navigator.clipboard.writeText(code) - cowAnalytics.sendEvent({ - category: WidgetCategory.WIDGET_CONFIGURATOR, - action: 'Copy code', - }) - setSnackbarOpen(true) + navigator.clipboard.writeText(code) + .then(() => { + cowAnalytics.sendEvent({ + category: WidgetCategory.WIDGET_CONFIGURATOR, + action: 'Copy code', + label: 'success', + }) + setSnackbarOpen(true) + }) + .catch((error) => { + cowAnalytics.sendEvent({ + category: WidgetCategory.WIDGET_CONFIGURATOR, + action: 'Copy code', + label: 'error', + error: error.message, + }) + // Handle error UI feedback + }) }apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.tsx (1)
187-193
: Consider enhancing error analytics 🔍The error tracking could be more detailed by including error types or codes in the analytics event.
Consider modifying the error analytics to include more context:
- sendTwapConversionAnalytics('rejected', fallbackHandlerIsNotSet) + sendTwapConversionAnalytics(`rejected:${error.name || 'unknown'}`, fallbackHandlerIsNotSet)apps/cow-fi/components/CareersPageContent.tsx (1)
19-21
: Clean up these imports, young calf! 🐮Please fix the import organization and remove the unused import:
import { Link, LinkType } from '@/components/Link' + import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { CowFiCategory } from 'src/common/analytics/types'Also applies to: 23-23
🧰 Tools
🪛 ESLint
[error] 19-19: There should be at least one empty line between import groups
(import/order)
[error] 20-20: There should be at least one empty line between import groups
(import/order)
[error] 20-20: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts (1)
110-116
: Consider adding more context to the analytics event.While the current implementation works, we could enhance the analytics by including additional context about the price ranges.
const label = `${order.inputToken.symbol}, ${order.outputToken.symbol}` -priceOutOfRangeAnalytics(label) +priceOutOfRangeAnalytics(`${label} | Market: ${marketPrice.toSignificant(6)} | Order: ${orderPrice.toSignificant(6)}`)apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx (1)
119-125
: Moo-ve that analytics event to a separate effect!The analytics event for opening the Advanced Orders Tab should be in its own effect to maintain separation of concerns.
useEffect(() => { updateSettingsState({ isFallbackHandlerSetupAccepted: false }) +}, [updateSettingsState]) + +useEffect(() => { cowAnalytics.sendEvent({ category: CowSwapCategory.TWAP, action: 'Open Advanced Orders Tab', }) -}, [updateSettingsState, cowAnalytics]) +}, [cowAnalytics])apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx (1)
182-191
: Moo-ve over GA4, GTM is here!The Max button implementation with GTM event tracking is clean and follows our new pattern.
However, consider adding a disabled state to prevent multiple rapid clicks:
<styledEl.SetMaxBtn data-click-event={toCowSwapGtmEvent({ category: CowSwapCategory.TRADE, action: 'Set Maximum Sell Tokens', })} onClick={handleMaxInput} + disabled={!maxBalance || maxBalance.equalTo(0)} > Max </styledEl.SetMaxBtn>
apps/cow-fi/data/cow-amm/const.tsx (1)
2-3
: Remove unused importtoCowFiGtmEvent
.The
toCowFiGtmEvent
import is not used in this file.-import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { CowFiCategory } from 'src/common/analytics/types'Also applies to: 28-28
🧰 Tools
🪛 ESLint
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 3-3: There should be at least one empty line between import groups
(import/order)
[error] 3-3:
src/common/analytics/types
import should occur after import of@cowprotocol/assets/images/image-cowamm-lp-4.svg
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/LearnPageComponent.tsx (1)
31-33
: MOOve these imports to maintain order! 🐮The imports need to be reorganized to follow the project's import ordering convention:
- External imports
- Internal absolute imports
- Internal relative imports
Apply this ordering:
-import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' import { Color, Font, Media } from '@cowprotocol/ui' +import { initGtm } from '@cowprotocol/analytics' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 31-31: There should be at least one empty line between import groups
(import/order)
[error] 31-31:
@cowprotocol/analytics
import should occur before import of../hooks/useLazyLoadImages
(import/order)
[error] 32-32: There should be at least one empty line between import groups
(import/order)
[error] 32-32:
src/common/analytics/types
import should occur before import of../hooks/useLazyLoadImages
(import/order)
[error] 32-32: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 33-33: There should be at least one empty line between import groups
(import/order)
[error] 33-33:
@cowprotocol/ui
import should occur before import of../hooks/useLazyLoadImages
(import/order)
apps/cow-fi/app/(main)/cow-amm/page.tsx (1)
12-13
: Moo! Let's organize these imports properly.The imports should be grouped and ordered correctly:
- External packages
- Internal modules
import { Color, ProductLogo, ProductVariant } from '@cowprotocol/ui' +import { initGtm } from '@cowprotocol/analytics' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' + import IMG_ICON_CROWN_COW from '@cowprotocol/assets/images/icon-crown-cow.svg' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 12-12: There should be at least one empty line between import groups
(import/order)
[error] 12-12:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 13-13:
src/common/analytics/types
import should occur before import of@/components/FAQ
(import/order)
[error] 13-13: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/widget/page.tsx (2)
4-5
: Let's keep our imports tidy and organized!The imports should follow a consistent order:
- External packages
- Internal modules
import { Font, Color, ProductLogo, ProductVariant } from '@cowprotocol/ui' +import { initGtm } from '@cowprotocol/analytics' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' + import IMG_ICON_OWL from '@cowprotocol/assets/images/icon-owl.svg' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
81-86
: Consider extracting duplicate event handlers into reusable functions.The same event handlers are duplicated in multiple places. Let's make it more DRY by creating reusable functions:
+const handleConfigureWidgetClick = () => + analytics.sendEvent({ + category: CowFiCategory.WIDGET, + action: 'click-config-widget', + }) + +const handleReadDocsClick = () => + analytics.sendEvent({ + category: CowFiCategory.WIDGET, + action: 'click-read-docs', + }) // Then use these functions in onClick handlers: onClick={handleConfigureWidgetClick} onClick={handleReadDocsClick}Also applies to: 99-104, 307-312, 325-330
apps/cow-fi/components/DaosPageComponent.tsx (1)
34-35
: Time to organize these imports properly!Let's maintain a consistent import order:
- External packages
- Internal modules
import { Link, LinkType } from '@/components/Link' +import { initGtm } from '@cowprotocol/analytics' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' + import 'swiper/css' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 34-34: There should be at least one empty line between import groups
(import/order)
[error] 35-35:
src/common/analytics/types
import should occur after import of@cowprotocol/assets/images/icon-ghost.svg
(import/order)
[error] 35-35: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/cow-swap/page.tsx (2)
6-7
: Let's maintain consistent import ordering!Organize imports following the standard pattern:
- External packages
- Internal modules
import { Color, ProductLogo, ProductVariant } from '@cowprotocol/ui' +import { initGtm } from '@cowprotocol/analytics' +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' + import IMG_ICON_UNICORN from '@cowprotocol/assets/images/icon-unicorn.svg' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 6-6: There should be at least one empty line between import groups
(import/order)
[error] 6-6:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 7-7: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
92-97
: Consider adding labels to analytics events for better tracking.The events could benefit from including labels to provide more context:
analytics.sendEvent({ category: CowFiCategory.COWSWAP, action: 'click-launch-app', + label: 'hero-section', // or 'footer-section' for the bottom button })
Also applies to: 130-135, 196-201, 414-419
apps/cow-fi/data/mev-blocker/const.tsx (1)
2-3
: Fix import order to follow project conventions.The imports should be grouped and ordered according to our project conventions:
- External dependencies
- Internal modules
- Assets
import { Link } from '@/components/Link' + import { initGtm } from '@cowprotocol/analytics' import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' + import IMG_LOGO_SAFE from '@cowprotocol/assets/images/logo-safe.svg'🧰 Tools
🪛 ESLint
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 2-2:
@cowprotocol/ui
import should occur after import of@cowprotocol/assets/images/image-profit.svg
(import/order)
[error] 3-3:
src/common/analytics/types
import should occur after import of@cowprotocol/assets/images/image-profit.svg
(import/order)
apps/cow-fi/data/cow-swap/const.tsx (1)
107-112
: Consider using data-click-event attribute for consistency.While the current implementation with onClick handlers works, consider using the data-click-event attribute pattern for consistency with other files (like mev-blocker/const.tsx).
Example transformation:
- onClick={() => - analytics.sendEvent({ - category: CowFiCategory.COWSWAP, - action: 'click-introduction-intents', - }) - } + data-click-event={toCowFiGtmEvent({ + category: CowFiCategory.COWSWAP, + action: 'Click Introduction Intents', + })}Also applies to: 121-125, 137-141, 152-155, 166-169, 199-203, 216-220, 243-247, 284-288, 310-314, 329-333, 344-348, 359-363, 374-378, 389-393, 419-423
apps/cow-fi/app/(main)/legal/widget-terms/page.tsx (1)
4-5
: Reorder imports for better organization.The imports need to be reordered according to our style guide:
-import { Color } from '@cowprotocol/ui' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { initGtm } from '@cowprotocol/analytics' +import { Color } from '@cowprotocol/ui' + +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/legal/cowswap-cookie-policy/page.tsx (1)
4-5
: Reorder imports for better organization.The imports need to be reordered according to our style guide:
-import { Color } from '@cowprotocol/ui' -import { initGtm } from '@cowprotocol/analytics' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' +import { initGtm } from '@cowprotocol/analytics' +import { Color } from '@cowprotocol/ui' + +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/data/cow-protocol/const.tsx (1)
33-36
: Reorder imports for better organization.The imports need to be reordered according to our style guide:
+import { useCowAnalytics } from '@cowprotocol/analytics' + +import { ReactNode } from 'react' + +import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' -import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' -import { ReactNode } from 'react' -import { useCowAnalytics } from '@cowprotocol/analytics'🧰 Tools
🪛 ESLint
[error] 33-33: There should be at least one empty line between import groups
(import/order)
[error] 33-33:
src/common/analytics/types
import should occur after import of@cowprotocol/analytics
(import/order)
[error] 34-34: There should be at least one empty line between import groups
(import/order)
package.json (1)
346-346
: Ensuring Proper File Termination
The addition of a newline at the end of the file is a good practice that can help avoid potential issues with some tools and version control systems.apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/index.tsx (1)
923-927
: Consider extracting common event data.The cancel event data is duplicated in multiple places. Consider extracting it to a constant to maintain DRY principles.
+const CANCEL_ORDER_EVENT = toCowSwapGtmEvent({ + category: CowSwapCategory.PROGRESS_BAR, + action: 'Click Cancel Order', + label: isSolved ? 'Solved' : 'Solving', +}) -const cancelEventData = toCowSwapGtmEvent({ - category: CowSwapCategory.PROGRESS_BAR, - action: 'Click Cancel Order', - label: isSolved ? 'Solved' : 'Solving', -}) -<styledEl.CancelButton data-click-event={cancelEventData} onClick={showCancellationModal}> +<styledEl.CancelButton data-click-event={CANCEL_ORDER_EVENT} onClick={showCancellationModal}>Also applies to: 958-960, 973-975
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (145)
apps/cow-fi/app/(main)/careers/refer-to-earn/page.tsx
(2 hunks)apps/cow-fi/app/(main)/cow-amm/page.tsx
(4 hunks)apps/cow-fi/app/(main)/cow-protocol/page.tsx
(14 hunks)apps/cow-fi/app/(main)/cow-swap/page.tsx
(6 hunks)apps/cow-fi/app/(main)/legal/cowswap-cookie-policy/page.tsx
(19 hunks)apps/cow-fi/app/(main)/legal/cowswap-privacy-policy/page.tsx
(14 hunks)apps/cow-fi/app/(main)/legal/cowswap-terms/page.tsx
(9 hunks)apps/cow-fi/app/(main)/legal/page.tsx
(3 hunks)apps/cow-fi/app/(main)/legal/widget-terms/page.tsx
(4 hunks)apps/cow-fi/app/(main)/page.tsx
(7 hunks)apps/cow-fi/app/(main)/widget/page.tsx
(7 hunks)apps/cow-fi/app/(mev-blocker)/mev-blocker/page.tsx
(9 hunks)apps/cow-fi/app/providers.tsx
(1 hunks)apps/cow-fi/components/AddRpcButton/index.tsx
(5 hunks)apps/cow-fi/components/ArticlePageComponent.tsx
(6 hunks)apps/cow-fi/components/ArticlesList.tsx
(2 hunks)apps/cow-fi/components/ArticlesPageComponents.tsx
(3 hunks)apps/cow-fi/components/CareersPageContent.tsx
(4 hunks)apps/cow-fi/components/CategoryLinks.tsx
(2 hunks)apps/cow-fi/components/DaosPageComponent.tsx
(7 hunks)apps/cow-fi/components/Layout/const.ts
(3 hunks)apps/cow-fi/components/LearnPageComponent.tsx
(7 hunks)apps/cow-fi/components/NotFoundPageComponent.tsx
(2 hunks)apps/cow-fi/components/TokensList/index.tsx
(3 hunks)apps/cow-fi/components/TopicPageComponent.tsx
(4 hunks)apps/cow-fi/components/TopicsPageComponent.tsx
(2 hunks)apps/cow-fi/data/cow-amm/const.tsx
(6 hunks)apps/cow-fi/data/cow-protocol/const.tsx
(1 hunks)apps/cow-fi/data/cow-swap/const.tsx
(19 hunks)apps/cow-fi/data/home/const.tsx
(3 hunks)apps/cow-fi/data/mev-blocker/const.tsx
(16 hunks)apps/cow-fi/lib/analytics/brave.ts
(0 hunks)apps/cow-fi/lib/hooks/useAddRpcWithTimeout.ts
(0 hunks)apps/cow-fi/lib/hooks/useConnect.ts
(1 hunks)apps/cow-fi/lib/hooks/useConnectAndAddToWallet.ts
(6 hunks)apps/cow-fi/modules/analytics/events.ts
(0 hunks)apps/cow-fi/modules/analytics/index.ts
(0 hunks)apps/cow-fi/src/common/analytics/types.ts
(1 hunks)apps/cow-fi/theme/types.ts
(1 hunks)apps/cowswap-frontend/src/common/analytics/types.ts
(1 hunks)apps/cowswap-frontend/src/common/analytics/utils.ts
(1 hunks)apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx
(5 hunks)apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
(3 hunks)apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts
(3 hunks)apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx
(2 hunks)apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/index.tsx
(16 hunks)apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/styled.ts
(1 hunks)apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx
(3 hunks)apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx
(3 hunks)apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts
(5 hunks)apps/cowswap-frontend/src/cosmos.decorator.tsx
(2 hunks)apps/cowswap-frontend/src/cow-react/index.tsx
(2 hunks)apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx
(4 hunks)apps/cowswap-frontend/src/legacy/components/Header/AccountElement/index.tsx
(2 hunks)apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx
(2 hunks)apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts
(5 hunks)apps/cowswap-frontend/src/legacy/state/price/middleware.ts
(1 hunks)apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts
(4 hunks)apps/cowswap-frontend/src/modules/analytics/events.ts
(0 hunks)apps/cowswap-frontend/src/modules/analytics/index.ts
(0 hunks)apps/cowswap-frontend/src/modules/analytics/useAnalyticsReporterCowSwap.ts
(0 hunks)apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx
(4 hunks)apps/cowswap-frontend/src/modules/application/containers/App/index.tsx
(3 hunks)apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
(5 hunks)apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts
(4 hunks)apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx
(1 hunks)apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts
(7 hunks)apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx
(2 hunks)apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx
(4 hunks)apps/cowswap-frontend/src/modules/limitOrders/services/safeBundleFlow/index.ts
(4 hunks)apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts
(2 hunks)apps/cowswap-frontend/src/modules/limitOrders/utils/limitOrderSettingsAnalytics.ts
(1 hunks)apps/cowswap-frontend/src/modules/notifications/containers/NotificationBell.tsx
(2 hunks)apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx
(4 hunks)apps/cowswap-frontend/src/modules/notifications/containers/NotificationsList/index.tsx
(2 hunks)apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwapOrEthFlow.ts
(4 hunks)apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx
(3 hunks)apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx
(1 hunks)apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx
(6 hunks)apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts
(3 hunks)apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx
(3 hunks)apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx
(4 hunks)apps/cowswap-frontend/src/modules/tokensList/pure/ListItem/index.tsx
(3 hunks)apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts
(3 hunks)apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts
(3 hunks)apps/cowswap-frontend/src/modules/trade/state/alternativeOrder/hooks.ts
(2 hunks)apps/cowswap-frontend/src/modules/trade/utils/tradeFlowAnalytics.ts
(2 hunks)apps/cowswap-frontend/src/modules/tradeFlow/hooks/useHandleSwap.ts
(5 hunks)apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleApprovalFlow.ts
(5 hunks)apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts
(5 hunks)apps/cowswap-frontend/src/modules/tradeFlow/services/swapFlow/index.ts
(4 hunks)apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/SettingsTab/index.tsx
(3 hunks)apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/TransactionSettings/index.tsx
(9 hunks)apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx
(2 hunks)apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx
(0 hunks)apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx
(2 hunks)apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx
(4 hunks)apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.tsx
(8 hunks)apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx
(5 hunks)apps/cowswap-frontend/src/modules/wallet/containers/WatchAssetInWallet/index.tsx
(5 hunks)apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx
(2 hunks)apps/cowswap-frontend/src/modules/wallet/pure/WatchAssetInWallet/index.tsx
(3 hunks)apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
(4 hunks)apps/cowswap-frontend/src/modules/yield/updaters/LpTokensWithBalancesUpdater/index.ts
(1 hunks)apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
(5 hunks)apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx
(2 hunks)apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
(2 hunks)apps/cowswap-frontend/src/test-utils.tsx
(2 hunks)apps/cowswap-frontend/src/theme/ThemeProvider.tsx
(3 hunks)apps/cowswap-frontend/src/theme/types.ts
(1 hunks)apps/explorer/src/analytics/events.ts
(0 hunks)apps/explorer/src/analytics/index.ts
(0 hunks)apps/explorer/src/analytics/useAnalyticsReporterExplorer.ts
(0 hunks)apps/explorer/src/common/analytics/types.ts
(1 hunks)apps/explorer/src/components/orders/DetailsTable/index.tsx
(4 hunks)apps/explorer/src/explorer/ExplorerApp.tsx
(5 hunks)apps/explorer/src/theme/ThemeProvider.tsx
(3 hunks)apps/explorer/src/theme/types.ts
(1 hunks)apps/widget-configurator/src/app/analytics/events.ts
(0 hunks)apps/widget-configurator/src/app/analytics/index.ts
(0 hunks)apps/widget-configurator/src/app/configurator/index.tsx
(4 hunks)apps/widget-configurator/src/app/embedDialog/index.tsx
(5 hunks)apps/widget-configurator/src/common/analytics/types.ts
(1 hunks)apps/widget-configurator/src/main.tsx
(3 hunks)libs/analytics/src/context/CowAnalyticsContext.tsx
(1 hunks)libs/analytics/src/googleAnalytics/CowAnalyticsGoogle.ts
(0 hunks)libs/analytics/src/googleAnalytics/initGoogleAnalytics.ts
(0 hunks)libs/analytics/src/gtm/CowAnalyticsGtm.ts
(1 hunks)libs/analytics/src/gtm/initGtm.ts
(1 hunks)libs/analytics/src/gtm/types.ts
(1 hunks)libs/analytics/src/hooks/useAnalyticsReporter.ts
(4 hunks)libs/analytics/src/index.ts
(1 hunks)libs/analytics/src/types.ts
(1 hunks)libs/common-hooks/src/useTheme.ts
(1 hunks)libs/common-utils/src/index.ts
(1 hunks)libs/common-utils/src/isIframe.ts
(1 hunks)libs/common-utils/src/isInjectedWidget.ts
(1 hunks)libs/ui/src/analytics/events.ts
(0 hunks)libs/ui/src/containers/ExternalLink/index.tsx
(2 hunks)libs/ui/src/containers/Footer/index.tsx
(3 hunks)libs/ui/src/index.ts
(1 hunks)libs/ui/src/theme/baseTheme.tsx
(2 hunks)libs/ui/src/theme/typings.ts
(3 hunks)libs/ui/src/types.ts
(1 hunks)package.json
(1 hunks)
💤 Files with no reviewable changes (16)
- apps/explorer/src/analytics/index.ts
- apps/cow-fi/modules/analytics/index.ts
- apps/cow-fi/lib/analytics/brave.ts
- apps/widget-configurator/src/app/analytics/index.ts
- apps/cowswap-frontend/src/modules/analytics/index.ts
- apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx
- apps/cow-fi/lib/hooks/useAddRpcWithTimeout.ts
- apps/cowswap-frontend/src/modules/analytics/useAnalyticsReporterCowSwap.ts
- libs/analytics/src/googleAnalytics/initGoogleAnalytics.ts
- libs/ui/src/analytics/events.ts
- apps/explorer/src/analytics/events.ts
- libs/analytics/src/googleAnalytics/CowAnalyticsGoogle.ts
- apps/widget-configurator/src/app/analytics/events.ts
- apps/explorer/src/analytics/useAnalyticsReporterExplorer.ts
- apps/cow-fi/modules/analytics/events.ts
- apps/cowswap-frontend/src/modules/analytics/events.ts
✅ Files skipped from review due to trivial changes (2)
- apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx
- apps/cowswap-frontend/src/modules/yield/updaters/LpTokensWithBalancesUpdater/index.ts
🧰 Additional context used
🪛 ESLint
apps/cow-fi/app/(main)/widget/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/cow-amm/page.tsx
[error] 12-12: There should be at least one empty line between import groups
(import/order)
[error] 12-12: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 13-13: src/common/analytics/types
import should occur before import of @/components/FAQ
(import/order)
[error] 13-13: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/providers.tsx
[error] 6-6: There should be at least one empty line between import groups
(import/order)
[error] 6-6: @cowprotocol/analytics
import should occur before import of ../services/uniswap-price/apollo-client
(import/order)
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 7-7: @apollo/client
import should occur before import of ../services/uniswap-price/apollo-client
(import/order)
[error] 8-8: There should be at least one empty line between import groups
(import/order)
[error] 9-9: There should be at least one empty line between import groups
(import/order)
[error] 9-9: react
import should occur before import of ../services/uniswap-price/apollo-client
(import/order)
[error] 10-10: styled-components/macro
import should occur before import of ../services/uniswap-price/apollo-client
(import/order)
[error] 11-11: next/navigation
import should occur before import of ../services/uniswap-price/apollo-client
(import/order)
[error] 12-12: react-inlinesvg/provider
import should occur before import of ../services/uniswap-price/apollo-client
(import/order)
apps/cow-fi/components/CareersPageContent.tsx
[error] 19-19: There should be at least one empty line between import groups
(import/order)
[error] 20-20: There should be at least one empty line between import groups
(import/order)
[error] 20-20: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/careers/refer-to-earn/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 6-6: There should be at least one empty line between import groups
(import/order)
apps/cow-fi/app/(main)/legal/cowswap-terms/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 8-8: There should be no empty line within import group
(import/order)
apps/cow-fi/components/TopicPageComponent.tsx
[error] 5-5: There should be at least one empty line between import groups
(import/order)
[error] 5-5: @cowprotocol/analytics
import should occur before import of styled-components/macro
(import/order)
[error] 6-6: There should be at least one empty line between import groups
(import/order)
[error] 6-6: src/common/analytics/types
import should occur before import of styled-components/macro
(import/order)
[error] 6-6: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 21-21: ../services/cms
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 21-21: 'Article' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/ArticlePageComponent.tsx
[error] 27-27: There should be at least one empty line between import groups
(import/order)
[error] 27-27: @cowprotocol/analytics
import should occur after import of react
(import/order)
[error] 28-28: There should be at least one empty line between import groups
(import/order)
[error] 28-28: src/common/analytics/types
import should occur after import of rehype-raw
(import/order)
[error] 28-28: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/AddRpcButton/index.tsx
[error] 1-1: There should be at least one empty line between import groups
(import/order)
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 2-2: @cowprotocol/ui
import should occur before import of src/common/analytics/types
(import/order)
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: polished
import should occur before import of src/common/analytics/types
(import/order)
[error] 5-5: There should be at least one empty line between import groups
(import/order)
[error] 6-6: wagmi
import should occur before import of ../../lib/hooks/useConnectAndAddToWallet
(import/order)
[error] 8-8: There should be at least one empty line between import groups
(import/order)
[error] 9-9: There should be at least one empty line between import groups
(import/order)
[error] 9-9: ../../types/addToWalletState
import should occur before import of @/components/Link
(import/order)
[error] 10-10: @cowprotocol/analytics
import should occur before import of src/common/analytics/types
(import/order)
apps/cow-fi/app/(main)/cow-swap/page.tsx
[error] 6-6: There should be at least one empty line between import groups
(import/order)
[error] 6-6: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 7-7: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/lib/hooks/useConnectAndAddToWallet.ts
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 7-7: @cowprotocol/analytics
import should occur before import of ./useConnect
(import/order)
[error] 8-8: src/common/analytics/types
import should occur before import of ./useConnect
(import/order)
[error] 8-8: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/ArticlesPageComponents.tsx
[error] 15-15: There should be at least one empty line between import groups
(import/order)
[error] 15-15: @cowprotocol/analytics
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 16-16: There should be at least one empty line between import groups
(import/order)
[error] 16-16: src/common/analytics/types
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 16-16: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 17-17: There should be at least one empty line between import groups
(import/order)
[error] 17-17: @/components/ArticlesList
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 18-18: There should be at least one empty line between import groups
(import/order)
[error] 18-18: ../services/cms
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 19-19: There should be at least one empty line between import groups
(import/order)
[error] 19-19: styled-components/macro
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 20-20: There should be at least one empty line between import groups
(import/order)
[error] 20-20: @cowprotocol/ui
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 21-21: next/link
import should occur before import of @/components/CategoryLinks
(import/order)
apps/cow-fi/lib/hooks/useConnect.ts
[error] 5-5: There should be at least one empty line between import groups
(import/order)
[error] 6-6: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/data/home/const.tsx
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 3-3: src/common/analytics/types
import should occur after import of react-inlinesvg
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/ArticlesList.tsx
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 3-3: There should be at least one empty line between import groups
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 5-5: services/cms
import should occur before import of src/common/analytics/types
(import/order)
apps/cow-fi/components/LearnPageComponent.tsx
[error] 31-31: There should be at least one empty line between import groups
(import/order)
[error] 31-31: @cowprotocol/analytics
import should occur before import of ../hooks/useLazyLoadImages
(import/order)
[error] 32-32: There should be at least one empty line between import groups
(import/order)
[error] 32-32: src/common/analytics/types
import should occur before import of ../hooks/useLazyLoadImages
(import/order)
[error] 32-32: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 33-33: There should be at least one empty line between import groups
(import/order)
[error] 33-33: @cowprotocol/ui
import should occur before import of ../hooks/useLazyLoadImages
(import/order)
[error] 34-34: There should be at least one empty line between import groups
(import/order)
[error] 34-34: @/components/LazySVG
import should occur before import of @/components/SearchBar
(import/order)
[error] 35-35: There should be at least one empty line between import groups
(import/order)
[error] 35-35: @cowprotocol/assets/images/icon-bulb-cow.svg
import should occur before import of ../hooks/useLazyLoadImages
(import/order)
[error] 36-36: There should be at least one empty line between import groups
(import/order)
[error] 36-36: ../services/cms
import should occur before import of @/components/CategoryLinks
(import/order)
[error] 37-37: styled-components/macro
import should occur before import of ../hooks/useLazyLoadImages
(import/order)
apps/cow-fi/components/TopicsPageComponent.tsx
[error] 16-16: There should be at least one empty line between import groups
(import/order)
[error] 17-17: There should be at least one empty line between import groups
(import/order)
[error] 17-17: src/common/analytics/types
import should occur after import of @cowprotocol/ui
(import/order)
[error] 17-17: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 18-18: There should be at least one empty line between import groups
(import/order)
[error] 19-19: There should be at least one empty line between import groups
(import/order)
[error] 19-19: ../services/cms
import should occur after import of styled-components/macro
(import/order)
apps/cow-fi/components/CategoryLinks.tsx
[error] 3-3: There should be at least one empty line between import groups
(import/order)
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: src/common/analytics/types
import should occur after import of next/link
(import/order)
[error] 4-4: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 5-5: There should be at least one empty line between import groups
(import/order)
apps/cow-fi/data/mev-blocker/const.tsx
[error] 3-3: src/common/analytics/types
import should occur after import of @cowprotocol/assets/images/image-profit.svg
(import/order)
apps/cow-fi/app/(main)/legal/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 6-6: There should be at least one empty line between import groups
(import/order)
apps/cow-fi/components/DaosPageComponent.tsx
[error] 34-34: There should be at least one empty line between import groups
(import/order)
[error] 35-35: src/common/analytics/types
import should occur after import of @cowprotocol/assets/images/icon-ghost.svg
(import/order)
[error] 35-35: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/page.tsx
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 8-8: src/common/analytics/types
import should occur after import of @cowprotocol/assets/images/icon-grants-carton.svg
(import/order)
[error] 8-8: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/legal/cowswap-cookie-policy/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/TokensList/index.tsx
[error] 6-6: There should be at least one empty line between import groups
(import/order)
apps/cow-fi/data/cow-swap/const.tsx
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 3-3: src/common/analytics/types
import should occur after import of @cowprotocol/assets/images/image-cowswap-multiple.svg
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/components/Layout/const.ts
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 2-2: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/data/cow-amm/const.tsx
[error] 2-2: There should be at least one empty line between import groups
(import/order)
[error] 3-3: There should be at least one empty line between import groups
(import/order)
[error] 3-3: src/common/analytics/types
import should occur after import of @cowprotocol/assets/images/image-cowamm-lp-4.svg
(import/order)
[error] 3-3: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 4-4: @cowprotocol/assets/images/image-cowamm-lvr.svg
import should occur after import of @cowprotocol/assets/images/image-cowamm-lp-4.svg
(import/order)
apps/cow-fi/components/NotFoundPageComponent.tsx
[error] 5-5: There should be at least one empty line between import groups
(import/order)
[error] 6-6: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
apps/cow-fi/app/(main)/legal/cowswap-privacy-policy/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 8-8: There should be no empty line within import group
(import/order)
apps/cow-fi/app/(main)/cow-protocol/page.tsx
[error] 21-21: src/common/analytics/types
import should occur before import of @/components/FAQ
(import/order)
apps/cow-fi/app/(main)/legal/widget-terms/page.tsx
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 9-9: There should be no empty line within import group
(import/order)
apps/cow-fi/data/cow-protocol/const.tsx
[error] 33-33: There should be at least one empty line between import groups
(import/order)
[error] 33-33: src/common/analytics/types
import should occur after import of @cowprotocol/analytics
(import/order)
[error] 34-34: There should be at least one empty line between import groups
(import/order)
[error] 43-43: 'analytics' is assigned a value but never used. Allowed unused vars must match /^_/u.
(unused-imports/no-unused-vars)
🪛 Biome (1.9.4)
apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts
[error] 37-37: void is confusing inside a union type.
Unsafe fix: Use undefined instead.
(lint/suspicious/noConfusingVoidType)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Cypress
- GitHub Check: Setup
🔇 Additional comments (136)
apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/styled.ts (1)
116-120
: Consistent styling for interactive elements 🎨The styling for buttons and links within the Description component looks good. The consistent use of text decoration and color helps maintain visual hierarchy.
libs/ui/src/theme/typings.ts (5)
3-3
: MOOvelous theme type definition! 🐮The
CowSwapTheme
type nicely captures our seasonal themes like Halloween and Christmas alongside the standard dark/light modes. This will help maintain type safety across our theming system.
62-65
: Widget mode interface is well structured! 🎯The
WidgetThemeMode
interface cleanly separates widget-specific theme properties. This will be particularly useful for our widget configurator and iframe implementations.
67-69
: Theme interface composition looks great! 🌈The
CowProtocolTheme
interface nicely combinesColors
,ThemeUtils
, and our newWidgetThemeMode
. This composition provides a comprehensive type-safe theme structure.
71-73
: Module declaration is properly typed! 🎯The styled-components module declaration ensures type safety throughout our styled components by extending
DefaultTheme
with ourCowProtocolTheme
.
23-23
: New color properties look good! 🎨The addition of
bg3
andgrey1
to our color palette expands our theming capabilities. Just ensure these new colors are properly defined in all theme variants.Let's check if these colors are defined in all theme implementations:
Also applies to: 25-25
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Search for theme implementations to verify color definitions rg -l "createTheme|makeTheme" --type typescript # Then search for bg3 and grey1 usage rg "bg3|grey1" --type typescriptLength of output: 154
Let's re-run our verification using an updated file type filter. The previous commands used
--type typescript
which isn’t recognized. I’ll now run commands using the file typets
to capture all TypeScript files.
🏁 Script executed:
#!/bin/bash # Search for the theme implementations that use createTheme or makeTheme in TypeScript files rg -l "createTheme|makeTheme" --type ts # Then search within TypeScript files for occurrences of bg3 and grey1 rg "bg3|grey1" --type tsLength of output: 972
New Colors Confirmed in Theme Variants
Moo! The shell script outputs show that both bg3 and grey1 are clearly defined in our theme typing file (libs/ui/src/theme/typings.ts) and given explicit values in the baseTheme (libs/ui/src/theme/baseTheme.tsx). Their usage in various components across the cowswap-frontend confirms that these new color properties are properly implemented and available in all theme variants.
- Verified definitions in libs/ui/src/theme/typings.ts
- Color values provided for dark and light modes in libs/ui/src/theme/baseTheme.tsx
- Usage confirmed in multiple cowswap-frontend components
apps/cowswap-frontend/src/theme/types.ts (1)
1-1
: MOOving in the right direction with centralized theme types! 🐮Good job importing the shared theme type from our UI package. This helps maintain consistency across our herd of applications.
libs/analytics/src/index.ts (3)
10-12
: Holy CoW! These hooks are udderly fantastic! 🐄The React integration through context and hooks provides a clean, type-safe way to access analytics throughout the app.
1-4
: MOO-ve in the right direction! Core initialization looks good.The removal of GA4-specific exports and addition of GTM initialization aligns perfectly with our migration goals. The retention of pixel analytics maintains backward compatibility.
Let's ensure all GA4 initialization calls have been replaced:
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Search for any remaining GA4 initialization calls rg -i "initCowAnalyticsGoogle|CowAnalyticsGoogle|react-ga4"Length of output: 61
MOO-ve on, GTM is on track!
Our search for legacy GA4 initialization calls returned no matches, confirming that all such references have been successfully removed. The barrel file now correctly exports only the GTM and pixel analytics initializations, in line with our migration goals.
14-17
: Type system looking strong as an ox! 🐂The comprehensive type exports ensure proper event validation at compile time. The separation of base types and specific GTM types provides good flexibility.
Let's verify our type safety:
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Check for proper type usage across the codebase ast-grep --pattern 'GtmEvent<$_>'Length of output: 35
🏁 Script executed:
#!/bin/bash echo "Searching for 'export type GtmEvent' (definition) in the codebase:" rg "export type GtmEvent" --color=always echo -e "\n\nSearching for generic usage of 'GtmEvent<' in the codebase:" rg "GtmEvent<" --color=alwaysLength of output: 2436
Strong Generic Type Safety Confirmed, partner!
All the usage of GtmEvent across the repo is consistent and properly exported, ensuring robust compile-time validation. The type exports in libs/analytics/src/types.ts and their application throughout the codebase (e.g., in explorer, cow-fi, and widget-configurator modules) demonstrate that our type safety game is on point.libs/common-hooks/src/useTheme.ts (3)
1-7
: Solid import structure and client directive.
Everything looks correct for specifying a client-side module, and importing styled-components/macro is a nice approach for client-side usage. No major concerns here.
9-23
: Good SSR check and fallback logic.
The conditional usage of require('styled-components') on the server side versus styled-components/macro on the client side is a clever approach, ensuring SSR won't break. It may be beneficial to verify that the SSR environment loads the theme as expected with real-world usage (e.g., Next.js) just to confirm everything lines up properly. Otherwise, the typing looks robust, and the function's return type is explicit.
25-26
: Convenient re-export of styled.
Re-exporting styled from this file can be handy but also watch out for potential confusion if you have multiple ways to import styled across the codebase. Overall, it’s a straightforward improvement for developer experience.apps/cowswap-frontend/src/modules/trade/utils/tradeFlowAnalytics.ts (2)
1-1
: Analytics imports look consistent.
Importing from '@cowprotocol/analytics' and referencing the new CowSwapCategory is well aligned with the shift to GTM-based tracking. Good job keeping the naming consistent.Also applies to: 6-6
16-23
: Interface definition promotes clarity.
Defining TradeFlowAnalytics ensures the new analytics pattern remains well structured and type-safe. Thank you for documenting each function parameter.libs/analytics/src/gtm/initGtm.ts (7)
1-6
: Clear module documentation.
Providing a brief description of the module’s purpose (single initialization, SSR mentions) is helpful for new developers. Nice job adding these doc comments.
7-16
: Global declarations and imports.
Declaring the dataLayer on the window object is a standard approach for GTM. The separation of CowAnalyticsGtm and CowAnalytics is clean. No issues here.
17-23
: Singleton pattern variables.
This straightforward object "analytics" tracks the instance and gtmId. The default GTM ID is a handy fallback. Implementation aligns with the previously discussed feedback on avoiding multiple re-initializations.
25-31
: Documentation for initGtm.
The docstring nicely clarifies the function’s purpose and constraints, especially around single initialization. Very clear.
32-44
: Early return for SSR is effective.
Returning a CowAnalyticsGtm for SSR ensures server-side code doesn’t attempt to manipulate the DOM. The fallback looks correct, and reusing the same analytics.instance is a safe approach if already initialized. Good job.
46-79
: Script & no-script insertion logic.
The script injection approach is standard GTM practice. The try-catch with console.error allows debugging if loading fails. The method does precisely one insertion, aligning with the singleton approach. Looks solid.
81-87
: Reset logic for tests.
The __resetGtmInstance function is straightforward and restricted to test mode by checking NODE_ENV. This fosters reliable testing of analytics initialization. Nicely done.libs/analytics/src/gtm/CowAnalyticsGtm.ts (2)
42-44
: Double delay might leave us waiting in the pasture.You already debounce the page view, so introducing another 1-second setTimeout can cause artificially slow analytics updates. Confirm if this double delay is really intended.
160-166
: This check is spot-on, moo-ch appreciated!The code nicely preserves
0
or empty strings while removing onlyundefined
values. This addresses the past remark about losing falsy but defined values.apps/cow-fi/theme/types.ts (1)
3-4
: Moo-ve over, extra interfaces!Extending CowProtocolTheme directly streamlines the theming architecture. This helps keep things simple and maintainable.
apps/widget-configurator/src/common/analytics/types.ts (1)
3-6
: MOOve to a more descriptive enum nameAs previously suggested, let's give this enum more context by renaming it to
AnalyticsCategory
orWidgetAnalyticsCategory
.-export enum WidgetCategory { +export enum WidgetAnalyticsCategory { WIDGET_CONFIGURATOR = 'Widget Configurator', WIDGET = 'Widget', }apps/explorer/src/theme/types.ts (1)
16-16
: MOOvelous theme integration!The extension of
DefaultTheme
withCowProtocolTheme
looks great! This ensures type safety across our theming system. 🐮✨apps/explorer/src/common/analytics/types.ts (1)
17-17
: Clever type composition! 🎯The ExplorerGtmEvent type nicely combines Explorer-specific categories with common categories, giving us the best of both worlds.
apps/cowswap-frontend/src/common/analytics/utils.ts (1)
11-19
: MOO-velous debouncing implementation! 🐄The debounced analytics function helps prevent analytics overload during rapid trade amount changes. However, as noted in a previous review, this function might be better placed in the trade module.
Consider moving this function to
modules/trade
since it's logically connected only to trade widgets.Consider making the debounce delay configurable:
- }, 1000) + }, debounceDelay = 1000)libs/ui/src/types.ts (1)
3-5
: Clean as a cow's morning MOO! 🌅Nice reorganization of the theme types. Moving CowSwapTheme to a dedicated theme typings file makes perfect sense for better maintainability.
libs/analytics/src/context/CowAnalyticsContext.tsx (1)
11-11
: Udderly fantastic context implementation! 🥛The CowAnalyticsContext is well-structured and follows React's context best practices. The Provider implementation is clean and type-safe.
Also applies to: 17-19
apps/cowswap-frontend/src/legacy/state/price/middleware.ts (1)
22-26
: Excellent implementation of price estimation tracking! 🐮The event tracking implementation looks good:
- Correct category usage
- Appropriate nonInteraction flag
- Clear action description
apps/cow-fi/components/ArticlesList.tsx (1)
26-32
: Excellent event tracking implementation! 🎯The analytics event structure is well-defined with appropriate category, action, and label properties.
apps/cow-fi/src/common/analytics/types.ts (1)
7-27
: Well-structured analytics categories! 🐮Great job organizing the categories:
- Base categories are preserved
- Clear separation between core and base categories
- Descriptive category names
apps/cow-fi/components/NotFoundPageComponent.tsx (1)
24-30
: Great 404 page tracking implementation! 🎯The event tracking is well structured with appropriate:
- Category (ERROR404)
- Action (Click Home)
- Label (404-page)
libs/analytics/src/types.ts (1)
19-28
: Udderly great type definition for GTM events! 🐮The BaseGtmEvent interface is well-structured and provides all necessary fields for GTM tracking. The generic type parameter allows for app-specific category extensions.
libs/ui/src/index.ts (1)
7-7
: MOO-ving out old analytics, looking good! 🐮Clean removal of the legacy analytics reporter and proper organization of theme exports. This change aligns well with our GTM migration strategy.
apps/cowswap-frontend/src/theme/ThemeProvider.tsx (2)
17-25
: Great job on performance optimization! 🎉MOOvelous work on moving the widget mode detection outside the component! This prevents unnecessary recalculations.
38-46
: Clean theme object computationThe simplified theme computation logic looks great! Much cleaner than before. 🧹
apps/cowswap-frontend/src/modules/trade/state/alternativeOrder/hooks.ts (1)
13-25
: MOOving in the right direction with this analytics hook! 🐮The
useAlternativeModalAnalytics
hook is well-structured, properly encapsulating the analytics logic and managing dependencies correctly.apps/cowswap-frontend/src/common/analytics/types.ts (2)
7-36
: MOO! Let's make our category names more consistent! 🐄Previous feedback suggested renaming to
AnalyticsCategory
orCowSwapAnalyticsCategory
for better consistency.
38-39
: This type assertion looks like extra hay in our stack! 🌾The assertion is redundant since the values are implicitly inherited from AnalyticsCategory.
apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx (1)
69-77
: MOOvelous implementation of GTM tracking! 🎮The declarative event tracking using
data-click-event
is clean and follows best practices. The event category and action are well-defined.apps/cow-fi/lib/hooks/useConnect.ts (1)
22-26
: MOOtiful analytics tracking! 📊The wallet connection event tracking is well-implemented with proper category and action.
libs/ui/src/containers/ExternalLink/index.tsx (1)
57-65
: MOOvelous implementation of link handling! 🐄The click handler elegantly handles both regular and new tab scenarios while preserving ctrl/meta click functionality.
libs/common-utils/src/index.ts (1)
34-34
: Clean and well-organized export! 🎯The new export maintains the alphabetical ordering convention.
apps/cowswap-frontend/src/modules/limitOrders/utils/limitOrderSettingsAnalytics.ts (1)
15-15
: MOOve this file to the hooks directory! 🐄Since this is a hook, it should be in the
hooks
directory and nameduseLimitOrderSettingsAnalytics.ts
.apps/cowswap-frontend/src/modules/notifications/containers/NotificationBell.tsx (1)
67-75
: MOO-velous implementation of GTM event tracking! 🐮The declarative event tracking using
data-click-event
with structured GTM event data is well implemented. The dynamic label with unread count provides valuable context for analytics.apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts (1)
39-39
: Hay there! Nice analytics integration! 🌾The analytics integration through context is well structured. Good job updating the dependency array to include the analytics instance.
Also applies to: 51-51, 59-59
apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts (2)
36-39
: Udderly fantastic event tracking! 🐄The GTM event implementation for token switching is clean and well-structured.
18-19
: Moo-ve forward with ETH flow implementationThere's a TODO comment about ETH flow implementation. Let's verify if this still needs to be addressed.
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Search for any existing ETH flow implementations rg -l "ETH.*flow" --type ts --type tsxLength of output: 68
🏁 Script executed:
#!/bin/bash # Re-run the search for "ETH" related flow logic, explicitly searching TS and TSX files. rg -l "ETH.*flow" -g "*.ts" -g "*.tsx"Length of output: 425
Heads up, Cow Dev!
The ETH flow logic is clearly kicking around in our codebase (check out the implementations in the swap services and hooks), but our file at
• apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts
still carries a TODO reminder for integrating that ETH flow for SWAP. This tells us that while we have ETH flow pieces in place (see useHandleSwapOrEthFlow and signEthFlowOrderStep), the SWAP implementation in useSwitchTokensPlaces hasn’t yet incorporated these components.You might want to either update this file to leverage the existing ETH flow logic or revise the TODO comment if this integration is planned elsewhere.
apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx (1)
45-47
: Remove redundant handleConnect function 🐮The
handleConnect
function is just wrappingconnectWallet
without adding any value. We can useconnectWallet
directly.- const handleConnect = useCallback(() => { - connectWallet() - }, [connectWallet]) return ( <Web3StatusConnect id="connect-wallet" - onClick={handleConnect} + onClick={connectWallet} data-click-event={toCowSwapGtmEvent(connectWalletEvent)} faded={!account} >apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx (1)
7-7
: MOOving in the right direction with analytics imports! 🐮Clean import of analytics types and utilities.
apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts (1)
31-41
: Well-structured analytics for approval flow! 🎯The analytics implementation captures all key stages of the approval process. Good use of useCallback for performance optimization.
apps/cowswap-frontend/src/modules/wallet/pure/WatchAssetInWallet/index.tsx (1)
74-84
: Clean implementation of wallet analytics! 🐮Great job on:
- Memoizing the analytics event object
- Including both token symbol and wallet name for better tracking
- Using declarative data attributes for event tracking
apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts (1)
26-27
: Smart use of debounced analytics! 🎯Excellent performance optimization by debouncing trade amount analytics events.
apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts (2)
23-24
: Excellent use of debouncing! 🎯Great job implementing debounced analytics! This will help prevent excessive event firing during rapid user input.
40-41
:⚠️ Potential issueMOOve
resetTradeQuote
to the dependency arrayHey there! 🐮 I noticed that
resetTradeQuote
is used in the callback but missing from the dependencies array. This could lead to stale closure issues.- [naviageOnCurrencySelection, updateCurrencyAmount, resetTradeQuote], + [naviageOnCurrencySelection, updateCurrencyAmount, resetTradeQuote],Likely invalid or redundant comment.
apps/cow-fi/components/CategoryLinks.tsx (1)
99-108
: Analytics implementation looks udderly fantastic!The GTM event tracking is well-structured with clear category, action, and label parameters. Good job on maintaining consistency across click handlers.
Also applies to: 116-123
apps/cow-fi/components/Layout/const.ts (1)
100-105
: Navigation analytics looking sharp as a cow's horns!The GTM event tracking for navigation actions is well-implemented with consistent categorization and clear action labels.
Also applies to: 115-120
apps/cow-fi/components/TokensList/index.tsx (2)
46-50
: Moo! Nice analytics implementation for search tracking! 🐮The event tracking for token search is well structured and captures meaningful data.
84-88
: Moo! Great token click tracking implementation! 🎯The event tracking for token clicks includes both name and symbol, making it more informative for analytics.
apps/cowswap-frontend/src/modules/notifications/containers/NotificationsList/index.tsx (1)
55-60
: Moo! Excellent notification tracking implementation! 🔔The event tracking includes all essential data points:
- Category: NOTIFICATIONS
- Action: Click Notification Card
- Label: Title
- Value: ID
This will provide rich analytics data for notification engagement.
apps/cowswap-frontend/src/test-utils.tsx (1)
31-31
: Moo! Clean theme generation simplification! 🎨The removal of isInjectedWidget dependency makes the theme generation more straightforward.
apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx (1)
68-72
: Moo! Great event tracking for modal actions! 🎯The event tracking for close and cancel actions is well implemented using the declarative approach.
Also applies to: 97-100
apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx (2)
32-32
: MOOving analytics implementation in the right direction! 🐮The analytics implementation for list removal looks good, with proper event categorization and labeling.
Also applies to: 34-40
42-48
: Udderly perfect event tracking for list toggling! 🐄The toggle event implementation captures both enable/disable states correctly.
apps/cow-fi/components/TopicsPageComponent.tsx (1)
91-97
: Smooth as milk analytics implementation! 🥛The click tracking implementation for topics is well-structured with proper event categorization.
apps/cowswap-frontend/src/cow-react/index.tsx (1)
34-34
: Excellent GTM setup at the root level! 🌱Initializing GTM at the app root and providing it through CowAnalyticsProvider ensures consistent analytics tracking throughout the app.
Also applies to: 57-57
apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx (1)
23-27
: Grazing through some great analytics! 🌿The hook details click tracking is well-implemented with clear action and label.
apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx (1)
9-9
: MOO-velous analytics implementation! 🐮The GTM event tracking is well-structured with appropriate category (WALLET), clear actions, and useful labels. This will help us track user interactions with wallet connection flows effectively.
Also applies to: 90-94, 102-105
libs/analytics/src/hooks/useAnalyticsReporter.ts (1)
114-120
: MOO-tiful context tracking addition! 🐮The new context tracking for marketDimension and injectedWidgetAppId enhances our analytics capabilities with better data segmentation.
apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx (1)
99-99
: MOO-gnificent Toggle component update! 🐮The data-click-event prop addition is clean, type-safe, and follows our GTM migration pattern perfectly. The destructuring of the prop name is particularly well done.
Also applies to: 102-110, 121-121
apps/cowswap-frontend/src/cosmos.decorator.tsx (1)
107-111
: MOO-velous analytics provider placement! 🐮The CowAnalyticsProvider is correctly placed to ensure all child components have access to analytics capabilities.
apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx (2)
64-67
: LGTM! Analytics event structure is well-defined 🎯The event structure follows GTM best practices with clear category and action.
89-93
: LGTM! Declarative click tracking implementation 🎨Good use of data attributes for GTM click tracking.
apps/cow-fi/components/AddRpcButton/index.tsx (2)
44-48
: LGTM! Comprehensive error tracking 🎯Good practice to include detailed error context in analytics events.
81-85
: LGTM! Consistent event structure across click handlers 🎨Well-structured GTM events with clear categories and actions.
Also applies to: 98-101
apps/cow-fi/components/ArticlesPageComponents.tsx (1)
79-90
: LGTM! Consistent analytics implementation 🎯Good use of GTM events for user navigation tracking in both breadcrumbs and pagination.
Also applies to: 109-116
apps/cowswap-frontend/src/modules/tradeFlow/services/swapFlow/index.ts (1)
15-15
: MOOving analytics to dependency injection - nice! 🐮The refactoring to pass analytics as a parameter rather than importing it directly improves modularity and testability. The analytics calls are properly placed at key points in the trade flow.
Also applies to: 25-25, 70-70, 126-126, 133-133
apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx (1)
1-1
: MOO-velous analytics integration for token lists! 🐄The token list operations are now properly tracked using GTM events with appropriate category, action, and label parameters.
Also applies to: 21-21, 48-48, 90-103
apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx (1)
68-70
: Holy COW! Nice separation of concerns! 🐄The refactoring to split the error boundary into a core component and HOC is a great improvement:
- Core component focuses on error boundary logic
- HOC handles analytics integration
- Flexible error handling through props
Also applies to: 72-72, 144-152
apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts (1)
23-29
: MOO-tiful interface extraction! 🐄Clean extraction of parameters into a dedicated interface improves code readability and maintainability.
apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx (1)
186-189
: Excellent use of data attributes for analytics! 🎯Using data attributes for GTM events is a MOO-dern and clean approach. This decouples the analytics logic from the click handler implementation.
apps/explorer/src/explorer/ExplorerApp.tsx (1)
121-128
: LGTM! Clear analytics setup with good documentation.The analytics reporter setup is well-documented, explicitly stating why account and wallet are undefined for the Explorer app.
apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts (1)
50-62
: MOO-velous implementation of wrap event tracking! 🐮The
sendWrapEvent
function is well-structured with proper typing and consistent event parameter handling.apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts (1)
25-27
: MOOving in the right direction with the hook conversion! 🐮The conversion from a plain function to a React hook improves integration with React's lifecycle and follows best practices. The use of
useCallback
for memoization is particularly well done.Also applies to: 28-159
apps/cowswap-frontend/src/modules/limitOrders/services/safeBundleFlow/index.ts (1)
31-31
: Udderly fantastic analytics integration! 🐄The analytics integration is clean and consistent with the GTM migration pattern. The analytics parameter is properly typed and events are tracked at appropriate points in the flow.
Also applies to: 55-55, 152-152, 159-159
apps/cow-fi/app/(main)/page.tsx (1)
37-42
: Milking the analytics events perfectly! 🥛The
sendHomeEvent
implementation is clean and follows the new GTM pattern correctly.apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx (1)
84-89
: Holy cow! This is a great analytics implementation! 🐮The use of data attributes with
toCowSwapGtmEvent
is a clean and maintainable approach to event tracking. The consistent categorization of events underCowSwapCategory.PROGRESS_BAR
makes it easy to analyze related interactions.Also applies to: 93-98, 102-109, 124-131, 135-140, 147-152
apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/SettingsTab/index.tsx (2)
91-95
: MOOvelous implementation of declarative analytics tracking!The data-click-event attribute with structured GTM events provides clear tracking of recipient toggle states.
120-124
: MOOre great analytics implementation!Consistent event structure maintained for hooks toggle tracking.
apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx (1)
11-12
: MOOving in the right direction with analytics refactoring! 🐮Nice job centralizing the analytics logic into a dedicated hook. This makes the analytics implementation more maintainable and consistent.
Also applies to: 115-116
apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx (1)
80-90
: Udderly fantastic analytics implementation! 🐄Great job implementing structured analytics events for the claim lifecycle:
- Using proper category constants
- Tracking claim attempts, signatures, and failures
- Clear event labeling
Also applies to: 100-126
apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.tsx (1)
37-51
: Well-structured analytics types! 🎯Great job defining clear interfaces for analytics events. This ensures type safety and consistency in event tracking.
apps/cow-fi/components/CareersPageContent.tsx (1)
97-103
: Consistent click tracking implementation! 🎯Great job implementing structured click tracking for both job applications and referrals. The events are well-categorized and provide meaningful labels.
Also applies to: 134-140, 171-177
apps/cow-fi/app/(main)/careers/refer-to-earn/page.tsx (1)
28-37
: Moo-velous implementation of GTM event tracking!The analytics event for breadcrumb navigation is well structured with appropriate category, action, and label.
apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts (1)
58-67
: Moo-tiful analytics callback implementation!The
priceOutOfRangeAnalytics
callback is well implemented with proper dependencies.apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx (1)
129-144
: Moo-nificent wallet compatibility analytics!The implementation of wallet compatibility tracking is well structured and provides valuable insights.
apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx (2)
22-22
: MOO-ve over GA4, GTM is here! Nice analytics setup.The analytics imports are well-structured and follow the new GTM pattern.
63-67
: Consistent event tracking implementation across swap actions.The event tracking implementation follows a consistent pattern across different swap actions, making it easy to track and analyze user behavior.
Also applies to: 183-187, 233-237
apps/cow-fi/data/cow-amm/const.tsx (1)
79-82
: Well-structured analytics events for FAQ interactions.The event tracking for FAQ interactions is properly categorized and includes meaningful action descriptions.
apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx (2)
70-71
: Smart use of debouncing for trade amount analytics!The implementation uses debouncing for trade amount analytics, which is a great performance optimization for high-frequency events.
79-82
: Clear and concise event tracking for token switching.The event tracking for token switching is well-structured with appropriate category and action.
apps/cow-fi/components/ArticlePageComponent.tsx (2)
124-127
: Good defensive programming with null checks for article titles.The implementation properly checks for undefined titles before rendering, preventing potential runtime errors.
75-79
: Consistent event tracking across article interactions.The event tracking implementation is consistent across different article interactions (sharing, categories, featured articles, read more), making analytics data more reliable and easier to analyze.
Also applies to: 133-137, 190-194, 225-229
apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx (2)
284-286
: MOOve-tiful string formatting! 🐮The Twitter share text formatting using template literals improves readability.
382-389
: Well-structured GTM events for fortune cookie interactions! 🍪The event tracking implementation follows best practices by:
- Using consistent category (COW_FORTUNE)
- Clear action names ('Open Fortune Cookie', 'Share on Twitter')
Also applies to: 353-357
apps/cow-fi/components/LearnPageComponent.tsx (1)
181-189
: Consistent event tracking implementation across all interactions! 🎯The analytics implementation follows best practices by:
- Using consistent category (KNOWLEDGEBASE)
- Descriptive action names with proper context
- Proper event handling for all interactive elements
Also applies to: 213-217, 277-283, 304-308
libs/ui/src/containers/Footer/index.tsx (1)
240-245
: Clean and declarative event tracking implementation! 🎯The data-click-event attribute approach with toGtmEvent is:
- Declarative and easy to understand
- Consistent with GTM best practices
- Well-structured with proper category and action
apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/TransactionSettings/index.tsx (2)
67-80
: Let's make these types more generic! 🐮As suggested in a previous review, the action types could be generalized since they share the same values.
-type SlippageAnalyticsAction = 'Default' | 'Custom' -type DeadlineAnalyticsAction = 'Default' | 'Custom' +type TxSettingAction = 'Default' | 'Custom' interface SlippageAnalyticsEvent { category: CowSwapCategory.TRADE - action: `${SlippageAnalyticsAction} Slippage Tolerance` + action: `${TxSettingAction} Slippage Tolerance` value: number } interface DeadlineAnalyticsEvent { category: CowSwapCategory.TRADE - action: `${DeadlineAnalyticsAction} Order Expiration Time` + action: `${TxSettingAction} Order Expiration Time` value: number }
115-137
: Well-structured analytics event sending functions! 📊The implementation:
- Properly handles different value types
- Uses consistent event structure
- Follows GTM best practices
apps/cow-fi/app/(main)/cow-amm/page.tsx (1)
63-69
: Analytics events look good! Moo-ving in the right direction.The GTM event implementation is consistent and well-structured, with proper categorization and descriptive actions.
Also applies to: 102-108
apps/cow-fi/components/DaosPageComponent.tsx (1)
160-166
: Well-structured analytics events! Moo-velous job!The event tracking is consistent and includes all necessary information:
- Category: DAOS
- Action: Descriptive click actions
- Label: Clear identification of link targets
Also applies to: 225-231, 312-319, 333-339
apps/cow-fi/data/mev-blocker/const.tsx (2)
14-15
: LGTM! Analytics initialization follows best practices.The GTM initialization is correctly placed at the module level.
🧰 Tools
🪛 ESLint
[error] 14-14:
@cowprotocol/assets/images/image-mevblocker-review-1.svg
import should occur after import of@cowprotocol/assets/images/image-fastfree.svg
(import/order)
[error] 15-15:
@cowprotocol/assets/images/image-mevblocker-review-2.svg
import should occur after import of@cowprotocol/assets/images/image-fastfree.svg
(import/order)
168-171
: Consistent implementation of analytics events.The event tracking implementation is consistent across all links, using the correct category and descriptive action names. This will help track user interactions effectively in GTM.
Also applies to: 214-217, 248-251, 306-309, 326-329, 365-368, 389-392, 413-416, 425-428, 445-448
apps/explorer/src/components/orders/DetailsTable/index.tsx (1)
182-188
: LGTM! Clean analytics implementation for copy actions.The event tracking for copy actions is well-implemented:
- Uses the correct category (ExplorerCategory.ORDER_DETAILS)
- Provides descriptive action ('Copy')
- Includes the specific label for what was copied
apps/widget-configurator/src/app/configurator/index.tsx (1)
226-233
: LGTM! Clean analytics implementation for wallet connection.The wallet connection event tracking is well-implemented:
- Correctly uses useEffect for side effects
- Proper dependency array including cowAnalytics
- Clear event category and action naming
apps/cow-fi/app/(main)/legal/widget-terms/page.tsx (1)
34-55
: LGTM! Clean GTM implementation for breadcrumb tracking.The event tracking implementation looks good with proper categorization under
CowFiCategory.LEGAL
and clear action naming.apps/cow-fi/app/(mev-blocker)/mev-blocker/page.tsx (1)
116-119
: LGTM! Comprehensive GTM implementation for MEV Blocker interactions.The event tracking implementation is thorough and consistent:
- All clickable elements use
data-click-event
attributes- Events are properly categorized under
CowFiCategory.MEVBLOCKER
- Action names are descriptive and follow a consistent pattern
Also applies to: 152-155, 174-177, 208-211, 361-364, 446-449, 476-479, 523-526
apps/cow-fi/app/(main)/legal/cowswap-cookie-policy/page.tsx (2)
39-62
: LGTM! Clean GTM implementation for breadcrumb tracking.The event tracking implementation looks good:
- Proper categorization under
CowFiCategory.LEGAL
- Clear action naming with 'Click Breadcrumb'
- Additional context through labels ('home', 'legal')
202-219
: LGTM! Content updated to reflect GTM usage.The cookie policy content has been properly updated to reference Google Tag Manager instead of Google Analytics.
apps/cow-fi/data/cow-protocol/const.tsx (1)
37-415
: LGTM! Well-structured FAQ data with GTM tracking.The FAQ implementation looks good:
- Uses a custom hook for better organization
- Consistent event tracking with proper categorization
- Clear action names and descriptive labels
🧰 Tools
🪛 ESLint
[error] 43-43: 'analytics' is assigned a value but never used. Allowed unused vars must match /^_/u.
(unused-imports/no-unused-vars)
package.json (1)
69-244
: React-GA4 Dependency Removal Aligned with GTM Migration
The removal of the "react-ga4" dependency from the dependencies section is well aligned with the GTM migration objective outlined in the PR. Please double-check across the codebase to ensure that no GA4-related references remain, and that all analytics calls have been updated appropriately to use the new GTM-based implementation.apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleApprovalFlow.ts (2)
17-17
: LGTM! Analytics parameter properly added.The addition of the
analytics
parameter of typeTradeFlowAnalytics
improves type safety and makes the analytics dependency explicit.Also applies to: 29-29
45-45
: LGTM! Analytics calls updated consistently.The analytics calls have been updated to use the new
analytics
parameter consistently throughout the flow:
approveAndPresign
sign
error
Also applies to: 135-135, 145-145
apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts (2)
20-20
: LGTM! Analytics parameter properly added.The addition of the
analytics
parameter of typeTradeFlowAnalytics
improves type safety and makes the analytics dependency explicit.Also applies to: 31-31
52-52
: LGTM! Analytics calls updated consistently.The analytics calls have been updated to use the new
analytics
parameter consistently throughout the flow:
wrapApproveAndPresign
sign
error
Also applies to: 149-149, 159-159
apps/cow-fi/app/(main)/cow-protocol/page.tsx (2)
21-21
: LGTM! Analytics imports and data handling properly added.The changes properly integrate GTM analytics and improve data handling:
- Added imports for analytics types and event helpers
- Updated FAQ data handling to use the
useFaqData
hookAlso applies to: 62-62
🧰 Tools
🪛 ESLint
[error] 21-21:
src/common/analytics/types
import should occur before import of@/components/FAQ
(import/order)
80-83
: LGTM! GTM event tracking consistently implemented.Event tracking has been properly added to all interactive elements using
data-click-event
attributes. The events are well-structured with:
- Consistent category (
CowFiCategory.COWPROTOCOL
)- Clear and descriptive action names
Also applies to: 117-120, 169-172, 215-218, 241-244, 419-422, 452-455, 474-477, 519-522, 565-568
apps/cow-fi/app/(main)/legal/cowswap-privacy-policy/page.tsx (2)
4-5
: LGTM! Analytics initialization properly added.The changes properly integrate GTM analytics:
- Added imports for GTM initialization and event types
- Initialized GTM analytics instance
Also applies to: 12-12
🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4:
@cowprotocol/analytics
import should occur before import of@cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
33-54
: LGTM! GTM event tracking added to breadcrumbs.Event tracking has been properly added to breadcrumb navigation using
onClick
handlers. The events are well-structured with:
- Consistent category (
CowFiCategory.LEGAL
)- Clear action name (
'click-legal-breadcrumbs'
)apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/index.tsx (3)
3-3
: LGTM! Analytics imports look good.The imports align with the new GTM-based analytics architecture:
useCowAnalytics
hook for GTM integrationCowSwapCategory
andtoCowSwapGtmEvent
for type-safe event trackingAlso applies to: 39-39
270-270
: LGTM! Analytics initialization and initial step tracking.Good implementation of analytics tracking for the initial step:
- Proper initialization of analytics using the hook
- Event tracking with correct category and action
Also applies to: 283-289
598-602
: LGTM! Declarative click tracking implementation.Great use of
data-click-event
attributes for declarative tracking:
- Type-safe event structure using
toCowSwapGtmEvent
- Consistent category usage (
CowSwapCategory.PROGRESS_BAR
)- Meaningful action and label values
Also applies to: 869-888
apps/cow-fi/app/(main)/legal/cowswap-terms/page.tsx (1)
33-54
: LGTM! Analytics implementation for breadcrumb tracking.Good implementation of GTM event tracking for breadcrumb clicks:
- Proper initialization using
initGtm
- Consistent category usage (
CowFiCategory.LEGAL
)- Clear action name (
click-legal-breadcrumbs
)
/** @deprecated Use isWidget instead */ | ||
isInjectedWidgetMode: boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Let's verify the migration to isWidget
is complete
As we're deprecating isInjectedWidgetMode
, we should ensure all existing usages are updated to use isWidget
.
Let's search for any remaining usages:
🏁 Script executed:
#!/bin/bash
# Search for remaining usages of isInjectedWidgetMode
rg "isInjectedWidgetMode" --type ts --type tsx
Length of output: 74
🏁 Script executed:
#!/bin/bash
# Re-run the search for remaining usages of isInjectedWidgetMode
# in TypeScript (.ts) and TSX (.tsx) files using glob patterns.
rg "isInjectedWidgetMode" --glob "*.ts" --glob "*.tsx"
Length of output: 8519
Migration Incomplete: Still Finding References to isInjectedWidgetMode
Hey team, after running the searches, we’re still spotting multiple usages of the deprecated isInjectedWidgetMode in various files. A few highlights:
- apps/explorer/src/theme/ThemeProvider.tsx – Contains both a comment (“TODO: isInjectedWidgetMode is deprecated, use isWidget instead”) and a direct mapping.
- apps/cowswap-frontend/src/modules/application/containers/App/index.tsx – Several conditionals and assignments still reference isInjectedWidgetMode.
- Additional instances appear in files like OrdersPanel, NotificationBell, TradeWidgetForm, and others.
We’ll need to update these references to isWidget (or adjust the migration strategy) to complete the deprecation process.
export function isIframe(): boolean { | ||
return window.self !== window.top | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
MOOve carefully: Add SSR safety check
Hey there! 🐮 As a CoW who's seen many browser environments, I'd suggest adding an SSR safety check since the window
object isn't available during server-side rendering.
Here's a safer implementation:
export function isIframe(): boolean {
- return window.self !== window.top
+ return typeof window !== 'undefined' && window.self !== window.top
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export function isIframe(): boolean { | |
return window.self !== window.top | |
} | |
export function isIframe(): boolean { | |
return typeof window !== 'undefined' && window.self !== window.top | |
} |
export function isInjectedWidget(): boolean { | ||
return window.location.hash.includes('/widget') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
MOOve to a more robust implementation
Hey fellow farmer! 🐮 A couple of suggestions to make this more robust:
- Add SSR safety check for
window
- Use URL parsing instead of string includes for more reliable detection
Here's a safer implementation:
export function isInjectedWidget(): boolean {
- return window.location.hash.includes('/widget')
+ if (typeof window === 'undefined') return false
+
+ try {
+ const hash = new URL(window.location.href).hash
+ return hash.split('/').includes('widget')
+ } catch {
+ return false
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export function isInjectedWidget(): boolean { | |
return window.location.hash.includes('/widget') | |
} | |
export function isInjectedWidget(): boolean { | |
if (typeof window === 'undefined') return false | |
try { | |
const hash = new URL(window.location.href).hash | |
return hash.split('/').includes('widget') | |
} catch { | |
return false | |
} | |
} |
import { initGtm } from '@cowprotocol/analytics' | ||
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' | ||
|
||
const cowAnalytics = initGtm() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
MOOve those imports into proper order! 📦
Let's fix the import ordering and remove the unused import:
import { ConnectResult, PublicClient } from '@wagmi/core'
+
import { initGtm } from '@cowprotocol/analytics'
-import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
+import { CowFiCategory } from 'src/common/analytics/types'
const cowAnalytics = initGtm()
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import { initGtm } from '@cowprotocol/analytics' | |
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' | |
const cowAnalytics = initGtm() | |
import { ConnectResult, PublicClient } from '@wagmi/core' | |
import { initGtm } from '@cowprotocol/analytics' | |
import { CowFiCategory } from 'src/common/analytics/types' | |
const cowAnalytics = initGtm() |
🧰 Tools
🪛 ESLint
[error] 5-5: There should be at least one empty line between import groups
(import/order)
[error] 6-6: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
const toggle = () => { | ||
toggleList(list, enabled) | ||
setIsActive((state) => !state) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add analytics for toggle action! 🐮
Don't forget to track the toggle action itself, not just the click event.
const toggle = () => {
toggleList(list, enabled)
setIsActive((state) => !state)
+ // Track the actual state change
+ const newState = !enabled
+ createListEvent(`List ${newState ? 'Enabled' : 'Disabled'}`, list.source)
}
import { useAccount } from 'wagmi' | ||
|
||
import { Link, LinkType } from '@/components/Link' | ||
import { AddToWalletStateValues } from '../../types/addToWalletState' | ||
import { initGtm } from '@cowprotocol/analytics' | ||
|
||
const cowAnalytics = initGtm() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
MOOve GTM initialization to a higher level! 🐮
Initializing GTM at the component level could lead to multiple instances. Consider moving this to the app level or using a custom hook.
-const cowAnalytics = initGtm()
Create a new hook in a shared location:
// hooks/useAnalytics.ts
import { initGtm } from '@cowprotocol/analytics'
let analytics: ReturnType<typeof initGtm>
export function useAnalytics() {
if (!analytics) {
analytics = initGtm()
}
return analytics
}
cowAnalytics.sendEvent({ | ||
category: CowFiCategory.MEVBLOCKER, | ||
action: 'Wallet Connected', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove duplicate analytics event.
There's a duplicate 'Wallet Connected' event being sent. Let's trim this down to avoid double-counting our herd!
- cowAnalytics.sendEvent({
- category: CowFiCategory.MEVBLOCKER,
- action: 'Wallet Connected',
- })
connect()
.then((result) => {
if (result) {
console.debug('[useConnectAndAddToWallet] 🔌 Connected!')
cowAnalytics.sendEvent({
category: CowFiCategory.MEVBLOCKER,
action: 'Wallet Connected',
})
Also applies to: 112-115
import { initGtm } from '@cowprotocol/analytics' | ||
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moo-ve these imports around to fix the order.
Let's organize these imports according to our style guide:
-import { Color } from '@cowprotocol/ui'
-import { initGtm } from '@cowprotocol/analytics'
-import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
+import { initGtm } from '@cowprotocol/analytics'
+import { Color } from '@cowprotocol/ui'
+import { CowFiCategory } from 'src/common/analytics/types'
Also, we can remove the unused toCowFiGtmEvent
import.
🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
import { initGtm } from '@cowprotocol/analytics' | ||
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' | ||
|
||
import styled from 'styled-components/macro' | ||
import { Link } from '@/components/Link' | ||
|
||
import { ArticleContent, ArticleMainTitle, BodyContent, Breadcrumbs, ContainerCard } from '@/styles/styled' | ||
import { clickOnLegal } from '../../../../modules/analytics' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix import order.
The imports need to be reordered according to the project's conventions.
Apply this diff to fix the import order:
-import { Color } from '@cowprotocol/ui'
-import { initGtm } from '@cowprotocol/analytics'
-import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
+import { initGtm } from '@cowprotocol/analytics'
+import { Color } from '@cowprotocol/ui'
+import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
[error] 7-7: There should be at least one empty line between import groups
(import/order)
[error] 8-8: There should be no empty line within import group
(import/order)
import { initGtm } from '@cowprotocol/analytics' | ||
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix import ordering.
The imports need to be reorganized according to the static analysis hints:
- Group external imports first
- Group internal imports second
- No empty lines within groups
import { Color } from '@cowprotocol/ui'
+import { initGtm } from '@cowprotocol/analytics'
import styled from 'styled-components/macro'
+
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
import { Link } from '@/components/Link'
import { ArticleContent, ArticleMainTitle, BodyContent, Breadcrumbs, ContainerCard } from '@/styles/styled'
-import { initGtm } from '@cowprotocol/analytics'
-import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
const analytics = initGtm()
Also applies to: 12-12
🧰 Tools
🪛 ESLint
[error] 4-4: There should be at least one empty line between import groups
(import/order)
[error] 4-4: @cowprotocol/analytics
import should occur before import of @cowprotocol/ui
(import/order)
[error] 5-5: There should be no empty line within import group
(import/order)
[error] 5-5: 'toCowFiGtmEvent' is defined but never used.
(unused-imports/no-unused-imports)
… optional chaining
Report too large to display inline |
Analytics Architecture Refactor: GA4 to GTM Migration
Technical Overview
Comprehensive refactoring of the analytics implementation, migrating from Google Analytics 4 (GA4) to Google Tag Manager (GTM) while significantly improving type safety, performance, and maintainability.
Implementation Details
Analytics Architecture
react-ga4
to native GTM implementationdataLayer
Type System Enhancements
Event Tracking Implementation
dataLayer
typing and managementPerformance Optimizations
react-ga4
dependency (~76.5KB)Code Organization
libs/analytics/src/hooks/
types.ts
Migration Impact
Breaking Changes
Removal of GA4-specific implementations:
CowAnalyticsGoogle
classAPI Changes:
Performance Implications
Testing Requirements
GTM Configuration:
Event Tracking:
Type Safety:
Implementation Notes
GTM-TBX4BV5M
Related Changes
Summary by CodeRabbit