Skip to content

Conversation

bunsenstraat
Copy link
Collaborator

@bunsenstraat bunsenstraat commented Oct 1, 2025

Refactor: Comprehensive Matomo Tracking System Overhaul

Overview

This PR introduces a new MatomoManager class that completely refactors Remix's analytics tracking system, providing better privacy controls, type safety, and developer experience.

🔧 Key Improvements

Privacy & Mode Management:

  • Custom dimension tracking for anonymous vs cookie modes
  • Click dimension tracking (dimension 3) for user interaction analytics
  • Seamless mode switching without cookie persistence issues
  • Proper initialization flow for new users requiring consent
  • Pre-consent event queuing - events collected before user choice, sent after consent
  • Enhanced anonymity with disableBrowserFeatureDetection in anonymous mode
  • Bot detection system with 6-layer detection (user agent, automation flags, headless browsers, mouse behavior)
  • Mouse movement analysis to distinguish human users from automation tools
  • TrackingMode dimension set before bot detection event ensuring all events properly tagged

Custom Matomo Dimensions:

  • 📊 Tracks user's consent state ('cookie', 'anon')
  • 📊 click - Boolean flag indicating user-initiated click events
  • 📊 'visitor bot detection' - Classification of detected bots ('automation', 'crawler', 'human', etc.)

Custom Matomo Bot Domain:

  • Bot requests are sent ( optional ) to seperate domains on matomo

Code Architecture:

  • Centralized tracking via MatomoManager and TrackingContext
  • Type-safe event definitions in @remix-api
  • Eliminated direct window._paq usage across entire codebase
  • ESLint rules preventing direct _paq access
  • Simplified settings tab using plugin calls

Developer Experience:

  • Rich debugging methods exposed by MatomoManager
  • Event-driven architecture for UI state management
  • Comprehensive E2E tests for consent workflows
  • Consistent tracking patterns across all plugins

Cleanup:

  • Removed legacy loader.js
  • Eliminated _paq.push() confusion
  • Standardized all tracking calls

📋 Usage Examples

Type-Safe Event System

// Before: Manual _paq calls with no validation
_paq.push(['trackEvent', 'something', 'happened', 'maybe?'])

React Components (Context-based):

import { DebuggerEvents } from '@remix-api'
import { TrackingContext } from '@remix-ide/tracking'

const { trackMatomoEvent } = useContext(TrackingContext)
trackMatomoEvent?.(HomeTabEvents.featuredPluginsActionClick(pluginInfo.pluginTitle))
trackMatomoEvent?.(CompilerEvents.compiled('with_config_file_' + state.useFileConfiguration))
trackMatomoEvent?.(UdappEvents.safeSmartAccount('txExecuted', 'successfully'))

Plugin Classes (Direct calls):

import { trackMatomoEvent, BlockchainEvents, UdappEvents } from '@remix-api'

trackMatomoEvent(this, BlockchainEvents.deployWithProxy('modal ok confirmation'))
trackMatomoEvent(plugin, CompilerEvents.compiled(workspaceTemplateName))

🧪 Testing

  • Added comprehensive E2E test suite covering consent flows, mode switching, and queue management
  • Bot detection tests validating automation tool identification (35 assertions)
  • Consent workflow tests covering 8 different user scenarios (200+ assertions)
  • E2E state markers (matomo-bot-detection-complete, matomo-initialized, matomo-debug-plugin-loaded) eliminate flaky pause() calls
  • All existing functionality preserved with improved reliability
  • Tests pass consistently in both local and CI environments

📦 Core Files Added/Modified

New Matomo Core Files:

  • apps/remix-ide/src/app/matomo/MatomoManager.ts - Main tracking manager with queue, consent, and mode switching
  • apps/remix-ide/src/app/matomo/MatomoConfig.ts - Configuration and constants
  • apps/remix-ide/src/app/matomo/MatomoAutoInit.ts - Automatic initialization logic
  • apps/remix-ide/src/app/matomo/BotDetector.ts - Comprehensive bot detection with mouse behavior analysis
  • apps/remix-ide/src/app/matomo/MatomoDebugPlugin.ts - E2E testing helper for event inspection
  • apps/remix-ide/src/app/contexts/TrackingContext.tsx - React context provider for components
  • libs/remix-ide/src/lib/tracking/TrackingFunction.ts - Factory for creating tracking functions

Type Definitions & Events:

  • libs/remix-api/src/lib/plugins/matomo/core/base-types.ts - Core Matomo event types
  • libs/remix-api/src/lib/plugins/matomo/events/*.ts - Type-safe event builders by category

Plugin Integration:

  • apps/remix-ide/src/app/plugins/matomo.ts - Matomo plugin exposing tracking API

E2E Tests:

  • apps/remix-ide-e2e/src/tests/matomo-consent*.test.ts - Comprehensive consent flow tests
  • apps/remix-ide-e2e/src/tests/matomo-bot-detection.test.ts - Bot detection validation tests

Documentation:

  • docs/matomo-bot-detection.md - Detailed bot detection mechanism documentation

ci-bot added 6 commits October 7, 2025 06:50
Replace arbitrary pause() calls with DOM state markers (data-id attributes)
for more reliable E2E test assertions. This follows the existing pattern
used by 'compilerloaded' marker.

Changes:
- Add setE2EStateMarker() helper to MatomoManager
- Add markers: matomo-bot-detection-complete, matomo-initialized, matomo-debug-plugin-loaded
- Replace pause(2000-4000ms) with waitForElementPresent() in tests
- Remove extra stabilization pauses after compilerloaded

Benefits:
- Tests wait for actual state, not arbitrary times
- Faster test execution (no unnecessary delays)
- More reliable in different environments (CI vs local)
- Self-documenting test intent

Test results:
- Bot detection: 35/35 assertions passing (17.5s)
- Consent group 1: 67/67 assertions passing (20.4s)
public _paq = {
push: (args) => {
this.call('matomo' as any, 'track', args)
push: (args: any[]) => {
Copy link
Collaborator

@ioedeveloper ioedeveloper Oct 13, 2025

Choose a reason for hiding this comment

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

This function "push: (args...)" is not needed in the circom plugin, since _paq.push has been replaced with trackCircuitEvent throughout the class.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I replaced it now

trackMatomoEvent(remixClient, event);
};

// Legacy _paq compatibility layer for existing learneth tracking calls
Copy link
Collaborator

Choose a reason for hiding this comment

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

We do not need legacy support for _paq calls since we are replacing all of it.

Copy link
Collaborator Author

@bunsenstraat bunsenstraat Oct 14, 2025

Choose a reason for hiding this comment

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

OK! replaced it all

if (pluginLoader.current === 'queryParams') {
this.workspace.map((workspace) => {
_paq.push(['trackEvent', 'App', 'queryParams-activated', workspace])
this.track(AppEvents.queryParamsActivated(workspace))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we need event function calls (AppEvents, HomeTabEvent, etc) for enforcing strict typing for matomo tracking.

Copy link
Collaborator Author

@bunsenstraat bunsenstraat Oct 14, 2025

Choose a reason for hiding this comment

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

but functions take parameters right

so witout it trackMatomoEvent?.(HomeTabEvents.switchTo(lang))

would become trackMatomoEvent?.({ ...HomeTabEvents.switchTo, name: lang }) which seems impractical to me

and other events have two parameters, name and value.

so in this case we are safe

  ...
  switchTo: (name?: string, value?: string | number): HomeTabEvent => ({
    category: 'hometab',
    action: 'switchTo',
    name,
    value,
    isClick: true 
  })
} as const;```


```export interface HomeTabEvent extends MatomoEventBase {
  category: 'hometab';
  action: 
    | 'header'
    | 'filesSection'
    | 'scamAlert'
    | 'switchTo'
    | 'titleCard'
    | 'recentWorkspacesCard'
    | 'featuredPluginsToggle'
    | 'featuredPluginsActionClick'
    | 'updatesActionClick'
    | 'homeGetStarted'
    | 'startLearnEthTutorial'
    | 'featuredSection';
}```




ci-bot added 7 commits October 14, 2025 07:58
Resolved conflicts in:
- libs/remix-ui/run-tab/src/lib/actions/deploy.ts: Combined IPFS publishing with verification logic
- libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx: Kept both TrackingContext and VerificationSettingsUI imports
@Aniket-Engg Aniket-Engg merged commit 96a3d87 into master Oct 15, 2025
33 checks passed
@Aniket-Engg Aniket-Engg deleted the trackerfix branch October 15, 2025 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants