agentsclimarketplace

Analytics

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

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

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

Privacy-first analytics knowledge base - Plausible, PostHog, Umami, Vercel Analytics, cookie consent. Use when setting up analytics, tracking events, measuring conversions, or integrating analytics tools.

SKILL.md

11.5 KB, as published. Nobody here has run it

Analytics Skill

Knowledge base per analytics privacy-first in applicazioni frontend moderne.

Provider Raccomandati

ProviderTipoGDPRFree Tier
PlausiblePrivacy-first, no cookiesCompliantSelf-host
PostHogProduct analytics, feature flagsCompliant1M events/mese
UmamiOpen source, self-hostedCompliantUnlimited
Vercel AnalyticsWeb Vitals, Next.js nativeCompliant2500 events/mese

Plausible Analytics (Raccomandato)

Installazione

# Script tag (più semplice)
# Aggiungi in <head>

# Oppure pacchetto npm
pnpm add plausible-tracker

Setup con Script Tag

// app/layout.tsx
import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head>
        <Script
          defer
          data-domain="tuodominio.com"
          src="https://plausible.io/js/script.js"
          strategy="afterInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  )
}

Setup con NPM Package

// lib/analytics.ts
import Plausible from 'plausible-tracker'

export const plausible = Plausible({
  domain: 'tuodominio.com',
  apiHost: 'https://plausible.io', // o self-hosted
  trackLocalhost: false,
})

// Auto pageview tracking
export function enableAutoPageviews() {
  plausible.enableAutoPageviews()
}

// Custom events
export function trackEvent(
  eventName: string,
  props?: Record<string, string | number | boolean>
) {
  plausible.trackEvent(eventName, { props })
}

Provider Component

// components/analytics-provider.tsx
'use client'

import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'
import { plausible } from '@/lib/analytics'

export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    // Track pageview on route change
    const url = pathname + (searchParams.toString() ? `?${searchParams}` : '')
    plausible.trackPageview({ url })
  }, [pathname, searchParams])

  return <>{children}</>
}

Custom Events

// Tracking conversions
import { trackEvent } from '@/lib/analytics'

// Signup
function handleSignup() {
  trackEvent('Signup', { plan: 'free' })
}

// Purchase
function handlePurchase(amount: number) {
  trackEvent('Purchase', { 
    revenue: amount,
    currency: 'EUR' 
  })
}

// Feature usage
function handleFeatureUse(feature: string) {
  trackEvent('Feature Used', { feature })
}

// CTA Click
function handleCTAClick(location: string) {
  trackEvent('CTA Click', { location })
}

Goals e Conversions

// Track outbound links
<a 
  href="https://external.com" 
  onClick={() => trackEvent('Outbound Link', { url: 'https://external.com' })}
>
  External Link
</a>

// Track file downloads
<a 
  href="/files/guide.pdf"
  onClick={() => trackEvent('File Download', { file: 'guide.pdf' })}
>
  Download Guide
</a>

// Track form submissions
function onSubmit(data: FormData) {
  trackEvent('Form Submit', { form: 'contact' })
  // ... submit logic
}

PostHog (Product Analytics)

Installazione

pnpm add posthog-js posthog-node

Client Setup

// lib/posthog.ts
import posthog from 'posthog-js'

export function initPostHog() {
  if (typeof window !== 'undefined' && !posthog.__loaded) {
    posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
      api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://app.posthog.com',
      loaded: (posthog) => {
        if (process.env.NODE_ENV === 'development') {
          posthog.debug()
        }
      },
      capture_pageview: false, // Manual control
      capture_pageleave: true,
      autocapture: true,
    })
  }
  return posthog
}

export { posthog }

Provider

// components/posthog-provider.tsx
'use client'

import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'
import { initPostHog, posthog } from '@/lib/posthog'

export function PostHogProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    initPostHog()
  }, [])

  useEffect(() => {
    if (pathname) {
      let url = window.origin + pathname
      if (searchParams.toString()) {
        url += `?${searchParams.toString()}`
      }
      posthog.capture('$pageview', { $current_url: url })
    }
  }, [pathname, searchParams])

  return <>{children}</>
}

Identify Users

// Dopo login
import { posthog } from '@/lib/posthog'

function onLogin(user: User) {
  posthog.identify(user.id, {
    email: user.email,
    name: user.name,
    plan: user.plan,
    createdAt: user.createdAt,
  })
}

// Dopo logout
function onLogout() {
  posthog.reset()
}

Feature Flags

// lib/feature-flags.ts
import { posthog } from '@/lib/posthog'

export function isFeatureEnabled(flagKey: string): boolean {
  return posthog.isFeatureEnabled(flagKey) ?? false
}

export function getFeatureFlag(flagKey: string) {
  return posthog.getFeatureFlag(flagKey)
}

// Usage in component
function PricingPage() {
  const showNewPricing = isFeatureEnabled('new-pricing-page')

  return showNewPricing ? <NewPricing /> : <OldPricing />
}

// Con React hook
import { useFeatureFlagEnabled } from 'posthog-js/react'

function Component() {
  const showBetaFeature = useFeatureFlagEnabled('beta-feature')
  
  if (!showBetaFeature) return null
  return <BetaFeature />
}

Server-Side (Node)

// lib/posthog-server.ts
import { PostHog } from 'posthog-node'

export const posthogServer = new PostHog(process.env.POSTHOG_API_KEY!, {
  host: process.env.POSTHOG_HOST || 'https://app.posthog.com',
})

// Server-side event
export async function trackServerEvent(
  distinctId: string,
  event: string,
  properties?: Record<string, any>
) {
  posthogServer.capture({
    distinctId,
    event,
    properties,
  })
}

// Server-side feature flag
export async function getServerFeatureFlag(
  distinctId: string,
  flagKey: string
) {
  return posthogServer.getFeatureFlag(flagKey, distinctId)
}

Umami (Self-Hosted)

Docker Setup

# docker-compose.yml
version: '3'
services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: your-random-secret
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - umami-db:/var/lib/postgresql/data

volumes:
  umami-db:

Script Integration

// app/layout.tsx
<Script
  defer
  src="https://your-umami-instance.com/script.js"
  data-website-id="your-website-id"
/>

Custom Events

// Umami usa data attributes
<button data-umami-event="signup-click">
  Sign Up
</button>

<button data-umami-event="purchase" data-umami-event-amount="99">
  Buy Now
</button>

// O programmaticamente
declare global {
  interface Window {
    umami?: {
      track: (event: string, data?: Record<string, any>) => void
    }
  }
}

function trackUmamiEvent(event: string, data?: Record<string, any>) {
  window.umami?.track(event, data)
}

Vercel Analytics (Next.js Native)

Setup

pnpm add @vercel/analytics @vercel/speed-insights

Integration

// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
        <SpeedInsights />
      </body>
    </html>
  )
}

Custom Events

import { track } from '@vercel/analytics'

// Track custom event
track('Signup', { plan: 'pro' })
track('Purchase', { amount: 99, currency: 'EUR' })

Google Analytics (GA4) - Se Necessario

// components/google-analytics.tsx
'use client'

import Script from 'next/script'

const GA_ID = process.env.NEXT_PUBLIC_GA_ID

export function GoogleAnalytics() {
  if (!GA_ID) return null

  return (
    <>
      <Script
        src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}
        strategy="afterInteractive"
      />
      <Script id="google-analytics" strategy="afterInteractive">
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', '${GA_ID}');
        `}
      </Script>
    </>
  )
}

// Track events
export function trackGAEvent(action: string, category: string, label?: string, value?: number) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', action, {
      event_category: category,
      event_label: label,
      value: value,
    })
  }
}

Cookie Consent Banner

// components/cookie-consent.tsx
'use client'

import { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'

export function CookieConsent() {
  const [showBanner, setShowBanner] = useState(false)

  useEffect(() => {
    const consent = localStorage.getItem('cookie-consent')
    if (!consent) {
      setShowBanner(true)
    }
  }, [])

  const acceptAll = () => {
    localStorage.setItem('cookie-consent', 'all')
    setShowBanner(false)
    // Enable analytics
    initAnalytics()
  }

  const acceptNecessary = () => {
    localStorage.setItem('cookie-consent', 'necessary')
    setShowBanner(false)
    // Only necessary cookies, no analytics
  }

  if (!showBanner) return null

  return (
    <div className="fixed bottom-0 left-0 right-0 bg-background border-t p-4 z-50">
      <div className="container flex flex-col sm:flex-row items-center justify-between gap-4">
        <p className="text-sm text-muted-foreground">
          Utilizziamo cookie per migliorare la tua esperienza.
          <a href="/privacy" className="underline ml-1">Privacy Policy</a>
        </p>
        <div className="flex gap-2">
          <Button variant="outline" size="sm" onClick={acceptNecessary}>
            Solo necessari
          </Button>
          <Button size="sm" onClick={acceptAll}>
            Accetta tutti
          </Button>
        </div>
      </div>
    </div>
  )
}

Environment Variables

# Plausible
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=tuodominio.com

# PostHog
NEXT_PUBLIC_POSTHOG_KEY=phc_xxx
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
POSTHOG_API_KEY=phx_xxx

# Umami
NEXT_PUBLIC_UMAMI_WEBSITE_ID=xxx

# Vercel Analytics (auto-configured on Vercel)

# Google Analytics (se necessario)
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX

Checklist Analytics

  • Provider privacy-first scelto (Plausible/PostHog/Umami)
  • Script/SDK installato
  • Pageview tracking attivo
  • Custom events definiti
  • Conversions/Goals configurati
  • Cookie consent banner (se necessario)
  • User identification (se app con auth)
  • Feature flags (se PostHog)
  • Dashboard configurata
  • GDPR compliance verificata

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.