agentsclimarketplace

Analytics tracking

Skill PIXARTSeu/Synapse/packages/codegraph/data/skill/analytics-tracking

Self-improving AI brain for Claude Code & Desktop — 28 MCP tools, 253 skills, collective memory, project tracking, work logs. One server, all your sessions share the same knowledge. Deploy on Coolify in 2 minutes.

Install
npx -y skills add PIXARTSeu/Synapse --skill analytics-tracking

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

When the user wants to set up, improve, or audit analytics tracking and measurement. Also use when the user mentions "set up tracking," "GA4," "Google Analytics," "conversion tracking," "event tracking," "UTM parameters," "tag manager," "GTM," "analytics implementation," or "tracking plan." Includes full Next.js TypeScript implementation. For A/B test measurement, see ab-testing.

SKILL.md

17.3 KB, as published. Nobody here has run it

Analytics Tracking

You are an expert in analytics implementation and measurement. Your goal is to help set up tracking that provides actionable insights for marketing and product decisions.

Initial Assessment

Check for product marketing context first: If .agents/product-marketing-context.md exists, read it before asking questions.

Before implementing tracking, understand:

  1. Business Context — What decisions will this data inform? What are key conversions?
  2. Current State — What tracking exists? What tools are in use?
  3. Technical Context — What's the tech stack? Any privacy/compliance requirements?

Core Principles

  1. Track for Decisions, Not Data — Every event should inform a decision. Avoid vanity metrics.
  2. Start with the Questions — What do you need to know? Work backwards to what you need to track.
  3. Name Things Consistently — Naming conventions matter. Establish patterns before implementing.
  4. Maintain Data Quality — Clean data > more data.

Event Naming Conventions

Recommended Format: Category_Action_Object

[category]_[action]_[object]

Categories: page, form, cta, content, video, exit

Examples:

  • cta_click_hero
  • form_submit_contact
  • content_scroll_50

Alternative: Object-Action

signup_completed
button_clicked
form_submitted
article_read
checkout_payment_completed

Best Practices:

  • Lowercase with underscores
  • Be specific: cta_hero_clicked vs. button_clicked
  • Include context in properties, not event name
  • Document all decisions

Event Taxonomy

Standard Events (Landing Page)

Event NameTriggerParameters
page_viewPage loadpage_path, page_title, page_locale, traffic_source
page_scrollScroll milestonesscroll_depth (25, 50, 75, 100)
page_timeTime thresholdstime_on_page (30s, 60s, 120s, 300s)
page_exitUser leavesexit_page, time_on_page, scroll_depth_final

CTA Events

Event NameTriggerParameters
cta_viewCTA enters viewportcta_id, cta_text, cta_location
cta_clickCTA clickedcta_id, cta_text, cta_location, cta_variant
cta_hoverCTA hovered (>500ms)cta_id, cta_location

Form Events

Event NameTriggerParameters
form_viewForm enters viewportform_id, form_name
form_startFirst field focusedform_id, first_field
form_field_completeField completedform_id, field_name, field_position
form_field_errorValidation errorform_id, field_name, error_type
form_abandonLeft without submitform_id, last_field, fields_completed
form_submitForm submittedform_id, form_name, submission_time
form_successSubmission confirmedform_id, lead_id
form_errorSubmission failedform_id, error_type

Content Engagement

Event NameTriggerParameters
content_section_viewSection enters viewportsection_id, section_name
content_testimonial_viewTestimonial seentestimonial_id, testimonial_author
content_faq_expandFAQ item expandedfaq_id, faq_question
content_pricing_viewPricing section seenpricing_tier_visible
content_feature_clickFeature clickedfeature_id, feature_name

Video Events

Event NameTriggerParameters
video_startVideo startsvideo_id, video_title
video_progressMilestonesvideo_id, progress (25, 50, 75, 100)
video_completeVideo endsvideo_id, watch_time
video_pausePausedvideo_id, pause_time

Exit Intent

Event NameTriggerParameters
exit_intent_triggerExit intent detectedtrigger_type (mouse, scroll, idle)
exit_popup_viewExit popup shownpopup_id, popup_variant
exit_popup_closePopup dismissedpopup_id, dismiss_method
exit_popup_convertPopup CTA clickedpopup_id, offer_type

Essential Events (Product/App)

EventProperties
onboarding_step_completedstep_number, step_name
feature_usedfeature_name
purchase_completedplan, value
subscription_cancelledreason

Implementation (Next.js + GA4)

Event Utility

// lib/analytics.ts
type EventParams = Record<string, string | number | boolean | undefined>

declare global {
  interface Window {
    gtag: (command: 'event', eventName: string, params?: EventParams) => void
    dataLayer: any[]
  }
}

export function trackEvent(eventName: string, params?: EventParams) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', eventName, {
      ...params,
      timestamp: new Date().toISOString(),
    })
  }

  if (process.env.NODE_ENV === 'development') {
    console.log('[Analytics]', eventName, params)
  }
}

// Typed event helpers
export const analytics = {
  pageView: (path: string, title: string, locale: string) =>
    trackEvent('page_view', { page_path: path, page_title: title, page_locale: locale }),

  pageScroll: (depth: 25 | 50 | 75 | 100) =>
    trackEvent('page_scroll', { scroll_depth: depth }),

  ctaClick: (id: string, text: string, location: string, variant?: string) =>
    trackEvent('cta_click', { cta_id: id, cta_text: text, cta_location: location, cta_variant: variant }),

  ctaView: (id: string, text: string, location: string) =>
    trackEvent('cta_view', { cta_id: id, cta_text: text, cta_location: location }),

  formStart: (formId: string, firstField: string) =>
    trackEvent('form_start', { form_id: formId, first_field: firstField }),

  formSubmit: (formId: string, formName: string) =>
    trackEvent('form_submit', { form_id: formId, form_name: formName }),

  formError: (formId: string, fieldName: string, errorType: string) =>
    trackEvent('form_field_error', { form_id: formId, field_name: fieldName, error_type: errorType }),

  formAbandon: (formId: string, lastField: string, fieldsCompleted: number) =>
    trackEvent('form_abandon', { form_id: formId, last_field: lastField, fields_completed: fieldsCompleted }),

  sectionView: (sectionId: string, sectionName: string) =>
    trackEvent('content_section_view', { section_id: sectionId, section_name: sectionName }),

  faqExpand: (faqId: string, question: string) =>
    trackEvent('content_faq_expand', { faq_id: faqId, faq_question: question }),
}

Scroll Tracking Hook

// hooks/use-scroll-tracking.ts
'use client'

import { useEffect, useRef } from 'react'
import { analytics } from '@/lib/analytics'

export function useScrollTracking() {
  const tracked = useRef<Set<number>>(new Set())

  useEffect(() => {
    const thresholds = [25, 50, 75, 100] as const

    const handleScroll = () => {
      const scrollHeight = document.documentElement.scrollHeight - window.innerHeight
      const scrollPercent = Math.round((window.scrollY / scrollHeight) * 100)

      thresholds.forEach((threshold) => {
        if (scrollPercent >= threshold && !tracked.current.has(threshold)) {
          tracked.current.add(threshold)
          analytics.pageScroll(threshold)
        }
      })
    }

    window.addEventListener('scroll', handleScroll, { passive: true })
    return () => window.removeEventListener('scroll', handleScroll)
  }, [])
}

Section Visibility Hook

// hooks/use-section-tracking.ts
'use client'

import { useEffect, useRef } from 'react'
import { analytics } from '@/lib/analytics'

export function useSectionTracking(sectionId: string, sectionName: string) {
  const ref = useRef<HTMLElement>(null)
  const hasTracked = useRef(false)

  useEffect(() => {
    const element = ref.current
    if (!element) return

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && !hasTracked.current) {
          hasTracked.current = true
          analytics.sectionView(sectionId, sectionName)
        }
      },
      { threshold: 0.5 }
    )

    observer.observe(element)
    return () => observer.disconnect()
  }, [sectionId, sectionName])

  return ref
}

// Usage
function HeroSection() {
  const sectionRef = useSectionTracking('hero', 'Hero Section')
  return (
    <section ref={sectionRef} id="hero">
      {/* content */}
    </section>
  )
}

Tracked CTA Component

// components/tracked-cta.tsx
'use client'

import { useEffect, useRef } from 'react'
import { Button } from '@/components/ui/button'
import { analytics } from '@/lib/analytics'

interface TrackedCTAProps {
  id: string
  location: 'hero' | 'pricing' | 'footer' | 'sticky'
  variant?: string
  children: React.ReactNode
  onClick?: () => void
}

export function TrackedCTA({ id, location, variant, children, onClick }: TrackedCTAProps) {
  const ref = useRef<HTMLButtonElement>(null)
  const hasTrackedView = useRef(false)

  useEffect(() => {
    const element = ref.current
    if (!element) return

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && !hasTrackedView.current) {
          hasTrackedView.current = true
          analytics.ctaView(id, element.textContent || '', location)
        }
      },
      { threshold: 0.5 }
    )

    observer.observe(element)
    return () => observer.disconnect()
  }, [id, location])

  const handleClick = () => {
    analytics.ctaClick(id, ref.current?.textContent || '', location, variant)
    onClick?.()
  }

  return (
    <Button ref={ref} onClick={handleClick}>
      {children}
    </Button>
  )
}

Form Tracking Hook

// hooks/use-form-tracking.ts
'use client'

import { useRef, useCallback, useEffect } from 'react'
import { analytics } from '@/lib/analytics'

export function useFormTracking(formId: string, formName: string) {
  const startTime = useRef<number | null>(null)
  const fieldsCompleted = useRef<string[]>([])
  const hasStarted = useRef(false)

  const trackStart = useCallback((fieldName: string) => {
    if (!hasStarted.current) {
      hasStarted.current = true
      startTime.current = Date.now()
      analytics.formStart(formId, fieldName)
    }
  }, [formId])

  const trackFieldComplete = useCallback((fieldName: string) => {
    if (!fieldsCompleted.current.includes(fieldName)) {
      fieldsCompleted.current.push(fieldName)
    }
  }, [])

  const trackError = useCallback((fieldName: string, errorType: string) => {
    analytics.formError(formId, fieldName, errorType)
  }, [formId])

  const trackSubmit = useCallback(() => {
    analytics.formSubmit(formId, formName)
  }, [formId, formName])

  const trackAbandon = useCallback(() => {
    if (hasStarted.current && fieldsCompleted.current.length > 0) {
      const lastField = fieldsCompleted.current[fieldsCompleted.current.length - 1]
      analytics.formAbandon(formId, lastField, fieldsCompleted.current.length)
    }
  }, [formId])

  useEffect(() => {
    const handleBeforeUnload = () => trackAbandon()
    window.addEventListener('beforeunload', handleBeforeUnload)
    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload)
      trackAbandon()
    }
  }, [trackAbandon])

  return { trackStart, trackFieldComplete, trackError, trackSubmit }
}

GA4 Configuration

Custom Dimensions

DimensionScopeDescription
page_localeEventLanguage (it, en, cs)
traffic_sourceSessionUTM source
cta_locationEventWhere CTA appears
form_idEventForm identifier
scroll_depthEventMax scroll reached
ab_variantSessionA/B test variant

Custom Metrics

MetricScopeDescription
time_to_cta_clickEventSeconds from page load to CTA click
form_completion_timeEventSeconds to complete form
fields_completedEventNumber of form fields filled

Conversions (Goals)

ConversionEventValue
Lead Generatedform_submit$50
Demo Requestedform_submit (demo form)$100
Pricing Viewedcontent_section_view (pricing)$5
High Engagementpage_scroll (100%) + time >120s$10

Quick Setup

  1. Create GA4 property and data stream
  2. Install gtag.js or GTM
  3. Enable enhanced measurement
  4. Configure custom events
  5. Mark conversions in Admin

UTM Strategy

Standard Parameters

utm_source    = [platform]         # google, linkedin, newsletter
utm_medium    = [channel type]     # cpc, social, email
utm_campaign  = [campaign name]    # q1-launch, product-feature
utm_content   = [ad/link variant]  # hero-cta, sidebar-banner
utm_term      = [keyword]          # frontend-development

UTM Preservation

// lib/utm.ts
export function getUtmParams(): Record<string, string> {
  if (typeof window === 'undefined') return {}

  const params = new URLSearchParams(window.location.search)
  const utmParams: Record<string, string> = {}
  const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']

  utmKeys.forEach((key) => {
    const value = params.get(key)
    if (value) {
      utmParams[key] = value
      sessionStorage.setItem(key, value)
    } else {
      const stored = sessionStorage.getItem(key)
      if (stored) utmParams[key] = stored
    }
  })

  return utmParams
}

export function getHiddenUtmFields() {
  const utms = getUtmParams()
  return Object.entries(utms).map(([key, value]) => (
    <input key={key} type="hidden" name={key} value={value} />
  ))
}

Dashboard KPIs

Primary Metrics

KPIFormulaTarget
Conversion Rate(form_submit / page_view) × 100>3%
CTA Click Rate(cta_click / cta_view) × 100>5%
Form Completion Rate(form_submit / form_start) × 100>60%
Bounce RateSingle page sessions / Total sessions<50%
Avg. Time on PageTotal time / Sessions>90s

Engagement Metrics

KPIFormulaTarget
Scroll Depth (Avg)Avg of final scroll_depth>75%
Content Section ViewsSections viewed per session>5
FAQ Engagementfaq_expand / page_view>20%
Video Play Ratevideo_start / page_view>15%

Funnel Metrics

Traffic → Page View → CTA Click → Form Start → Form Submit → Qualified Lead

Drop-off Analysis:
- Page View → CTA Click: [%] (Message clarity issue)
- CTA Click → Form Start: [%] (CTA mismatch issue)
- Form Start → Form Submit: [%] (Form friction issue)

A/B Testing Events

trackEvent('ab_test_exposure', {
  test_id: 'hero-headline-q1',
  variant: 'B',
  test_name: 'Hero Headline Test',
})

trackEvent('ab_test_conversion', {
  test_id: 'hero-headline-q1',
  variant: 'B',
  conversion_type: 'form_submit',
})

Privacy and Compliance

  • Cookie consent required in EU/UK/CA
  • No PII in analytics properties
  • Data retention settings in GA4
  • Use consent mode (wait for consent before tracking)
  • IP anonymization enabled
  • Only collect what you need

Debugging

Debug Mode

export function enableAnalyticsDebug() {
  if (typeof window !== 'undefined') {
    (window as any).analyticsDebug = true
  }
}

Common Issues

IssueCauseFix
Events not firingCSR hydrationUse useEffect
Duplicate eventsRe-rendersUse refs to track
Missing paramsAsync stateEnsure data ready
Wrong attributionUTM lostSession storage preservation

GA4 Debug View

  1. Install GA Debugger Chrome extension
  2. Enable debug mode: gtag('config', 'GA_ID', { debug_mode: true })
  3. View real-time in GA4 → Configure → DebugView

Tool Integrations

ToolBest ForGuide
GA4Web analytics, Google ecosystemMCP available
MixpanelProduct analytics, event tracking
PostHogOpen-source analytics, session replay
SegmentCustomer data platform, routing
AmplitudeProduct analytics, cohort analysis

Checklist

  • Event taxonomy defined
  • Analytics utility created
  • Scroll tracking implemented
  • CTA tracking on all buttons
  • Form tracking complete
  • Section visibility tracking
  • UTM preservation working
  • GA4 custom dimensions configured
  • Conversions defined in GA4
  • Debug mode available
  • Dashboard KPIs documented
  • A/B test events ready
  • Privacy/consent compliance verified

Related Skills

  • ab-testing: For experiment tracking
  • page-cro: For conversion optimization (uses this data)
  • revops: For pipeline metrics, CRM tracking, revenue attribution
  • measurement: See analytics-tracking (this skill replaces it)

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.