Skip to content
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

Open
wants to merge 37 commits into
base: develop
Choose a base branch
from

Conversation

fairlighteth
Copy link
Contributor

@fairlighteth fairlighteth commented Jan 30, 2025

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

  • Migrated from react-ga4 to native GTM implementation
  • Implemented type-safe GTM event tracking via dataLayer
  • Introduced declarative data-attribute based event tracking
  • Centralized analytics dimensions management
  • Improved analytics context propagation

Type System Enhancements

interface GtmEvent {
  category: Category
  action: string
  label?: string
  value?: number
  orderId?: string
  orderType?: string
  tokenSymbol?: string
  chainId?: number
}
  • Strict type checking for GTM events
  • Runtime validation via type guards
  • Comprehensive event categorization
  • Type-safe dimension handling

Event Tracking Implementation

  • Declarative click tracking:
data-click-event={toGtmEvent({
  category: Category.EXTERNAL_LINK,
  action: 'Click external link',
  label: anonymizedHref,
})}
  • Improved event validation:
function isValidGtmClickEvent(data: unknown): data is GtmClickEvent {
  // Type guard implementation for runtime safety
}
  • Proper dataLayer typing and management
  • Enhanced error tracking capabilities

Performance Optimizations

  • Removed react-ga4 dependency (~76.5KB)
  • Optimized event debouncing implementation
  • Improved analytics initialization
  • Better handling of SSR scenarios

Code Organization

  • Moved analytics reporter to libs/analytics/src/hooks/
  • Centralized event categories in types.ts
  • Improved module structure following DDD principles
  • Better separation of concerns

Migration Impact

Breaking Changes

  1. Removal of GA4-specific implementations:

    • CowAnalyticsGoogle class
    • GA4 event tracking methods
    • GA4 dimension mapping
  2. API Changes:

    • Event tracking now uses data attributes
    • Direct analytics calls replaced with GTM events
    • New type-safe event creation utilities

Performance Implications

  • Reduced bundle size by removing GA4 dependency
  • Improved event batching
  • Better handling of analytics initialization
  • Optimized SSR support

Testing Requirements

  1. GTM Configuration:

    • Verify GTM container setup
    • Validate event triggers
    • Check custom dimensions
  2. Event Tracking:

    • Validate click tracking
    • Verify page views
    • Test error tracking
    • Check custom events
  3. Type Safety:

    • Verify TypeScript integration
    • Test runtime type guards
    • Validate event validation

Implementation Notes

  • GTM Container ID: GTM-TBX4BV5M
  • Event validation is enforced at runtime
  • SSR-safe implementation
  • Maintains backwards compatibility with existing analytics data

Related Changes

  • Package updates (removed react-ga4)
  • Type system improvements
  • Module reorganization

Summary by CodeRabbit

  • New Features
    • Introduced a unified event tracking system via Google Tag Manager that enhances measurement of user interactions across the platform.
    • Updated legal and informational pages to clearly describe tracking and cookie practices.
  • Refactor
    • Consolidated and standardized analytics methods across many components for improved consistency and type safety.
  • Chores
    • Removed deprecated analytics libraries and streamlined theme and configuration logic for better maintainability and performance.

Copy link

vercel bot commented Jan 30, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
cowfi ✅ Ready (Inspect) Visit Preview Feb 7, 2025 5:11pm
explorer-dev ✅ Ready (Inspect) Visit Preview Feb 7, 2025 5:11pm
swap-dev 🛑 Canceled (Inspect) Feb 7, 2025 5:11pm
widget-configurator ✅ Ready (Inspect) Visit Preview Feb 7, 2025 5:11pm
2 Skipped Deployments
Name Status Preview Updated (UTC)
cosmos ⬜️ Ignored (Inspect) Visit Preview Feb 7, 2025 5:11pm
sdk-tools ⬜️ Ignored (Inspect) Visit Preview Feb 7, 2025 5:11pm

@fairlighteth
Copy link
Contributor Author

/apps/cow-fi not building - but is fixed in PR #5363

@shoom3301
Copy link
Collaborator

shoom3301 commented Feb 3, 2025

@fairlighteth amazing initiative!
There are two ideas I want to propose:

  1. Use "Click trigger" in GTM instead of analytics.sendEvent. For that we will only need to add ids to some elements
  2. Use "Custom event trigger" only if the first approach doesn't work

The main idea is to keep the GTM as independent as possible.
As a first step we need to migrate all onClick={() => analytics.sendEvent(...)} to the GTM side as click triggers:

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 {
Copy link
Collaborator

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.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor Author

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,
Copy link
Collaborator

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?

Copy link
Contributor Author

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'
Copy link
Collaborator

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

Copy link
Contributor Author

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 {
Copy link
Collaborator

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

Copy link
Contributor Author

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
Copy link
Collaborator

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,

Copy link
Contributor Author

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) {
Copy link
Collaborator

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)

Copy link
Contributor Author

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()
Copy link
Collaborator

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.

Copy link
Contributor Author

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) {
Copy link
Collaborator

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.

Copy link
Contributor Author

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'
Copy link
Collaborator

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'

Copy link
Contributor Author

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() {
Copy link
Collaborator

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

Copy link
Contributor Author

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(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks redundant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

Copy link

coderabbitai bot commented Feb 7, 2025

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 72ce985 and 6fc813f.

⛔ 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/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 (4 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 (6 hunks)
  • apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrderSettingsAnalytics.ts (1 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/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/index.ts (1 hunks)
  • apps/cowswap-frontend/src/modules/trade/state/alternativeOrder/hooks.ts (2 hunks)
  • apps/cowswap-frontend/src/modules/trade/utils/analytics.ts (1 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/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)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a 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 event

The same event is sent twice when importing a list - once in addCustomTokenLists and again in importListAndBack.

 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 suggestion

Remove 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 suggestion

MOOve 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 to styled.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:

  1. Use GTM's native "Click trigger" as the primary method (requires adding IDs to elements)
  2. Fall back to toGtmEvent for complex scenarios

This 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 middleware

As 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 groups

Let'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 of src/common/analytics/types

(import/order)

apps/cow-fi/src/common/analytics/types.ts (1)

37-42: Type casting could be improved

The 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 imports

Let'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 checking

MOOving 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 helper

Let'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 accessibility

Hey 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 component

As 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 code

Also 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 labels

Let'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 parameters

Consider 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 analytics

While 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 parameters

While 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 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/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 but data-click-event elsewhere. Let's standardize on data-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 instead
apps/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 environment
apps/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:

  1. External dependencies
  2. Internal utilities
  3. 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 analytics

While 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 operations

The 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 import toCowFiGtmEvent.

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:

  1. External imports
  2. Internal absolute imports
  3. 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:

  1. External packages
  2. 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:

  1. External packages
  2. 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:

  1. External packages
  2. 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:

  1. External packages
  2. 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:

  1. External dependencies
  2. Internal modules
  3. 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

📥 Commits

Reviewing files that changed from the base of the PR and between c630411 and 603e7be.

⛔ 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 combines Colors, ThemeUtils, and our new WidgetThemeMode. 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 our CowProtocolTheme.


23-23: New color properties look good! 🎨

The addition of bg3 and grey1 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 typescript

Length 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 type ts 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 ts

Length 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=always

Length 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 only undefined 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 name

As previously suggested, let's give this enum more context by renaming it to AnalyticsCategory or WidgetAnalyticsCategory.

-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 with CowProtocolTheme 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 computation

The 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 or CowSwapAnalyticsCategory 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 named useLimitOrderSettingsAnalytics.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 implementation

There'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 tsx

Length 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 wrapping connectWallet without adding any value. We can use connectWallet 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 issue

MOOve resetTradeQuote to the dependency array

Hey 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 under CowSwapCategory.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:

  1. Using consistent category (COW_FORTUNE)
  2. 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:

  1. Using consistent category (KNOWLEDGEBASE)
  2. Descriptive action names with proper context
  3. 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:

  1. Declarative and easy to understand
  2. Consistent with GTM best practices
  3. 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:

  1. Properly handles different value types
  2. Uses consistent event structure
  3. 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 type TradeFlowAnalytics 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 type TradeFlowAnalytics 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 hook

Also 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 integration
  • CowSwapCategory and toCowSwapGtmEvent for type-safe event tracking

Also 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)

Comment on lines +5 to 6
/** @deprecated Use isWidget instead */
isInjectedWidgetMode: boolean
Copy link

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.

Comment on lines +5 to +7
export function isIframe(): boolean {
return window.self !== window.top
}
Copy link

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.

Suggested change
export function isIframe(): boolean {
return window.self !== window.top
}
export function isIframe(): boolean {
return typeof window !== 'undefined' && window.self !== window.top
}

Comment on lines 5 to 7
export function isInjectedWidget(): boolean {
return window.location.hash.includes('/widget')
}
Copy link

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:

  1. Add SSR safety check for window
  2. 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.

Suggested change
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
}
}

Comment on lines +5 to +8
import { initGtm } from '@cowprotocol/analytics'
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'

const cowAnalytics = initGtm()
Copy link

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.

Suggested change
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)

Comment on lines 27 to 31
const toggle = () => {
toggleList(list, enabled)
setIsActive((state) => !state)
}

Copy link

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()
Copy link

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
}

Comment on lines +104 to +107
cowAnalytics.sendEvent({
category: CowFiCategory.MEVBLOCKER,
action: 'Wallet Connected',
})
Copy link

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

Comment on lines +4 to +5
import { initGtm } from '@cowprotocol/analytics'
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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)

Comment on lines +4 to +11
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'

Copy link

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)

Comment on lines +4 to +5
import { initGtm } from '@cowprotocol/analytics'
import { CowFiCategory, toCowFiGtmEvent } from 'src/common/analytics/types'
Copy link

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:

  1. Group external imports first
  2. Group internal imports second
  3. 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)

Copy link

Report too large to display inline

View full report↗︎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants