🍺HydrateBeer

What Gets Tracked

Learn what performance metrics HydrateBeer collects and sends to PostHog

Automatic Tracking

These events are tracked automatically when you add HydrateBeerProvider:

Page Views (hydratebeer_page_view)

Tracks every page navigation in your application.

PostHog Event:

{
  "event": "hydratebeer_page_view",
  "properties": {
    "path": "/products",
    "referrer": "/",
    "sessionId": "sess_xyz789...",
    "timestamp": "2025-01-06T10:30:00.000Z"
  },
  "distinct_id": "sess_xyz789...",
  "timestamp": "2025-01-06T10:30:00.000Z"
}

Captured Properties:

  • path - Current route/URL path
  • referrer - Previous page URL
  • sessionId - Anonymous session identifier
  • timestamp - ISO 8601 timestamp

Tracks route transitions and navigation timing.

PostHog Event:

{
  "event": "hydratebeer_navigation",
  "properties": {
    "from": "/",
    "to": "/products",
    "duration": 156,
    "sessionId": "sess_xyz789...",
    "timestamp": "2025-01-06T10:30:01.000Z"
  },
  "distinct_id": "sess_xyz789...",
  "timestamp": "2025-01-06T10:30:01.000Z"
}

Captured Properties:

  • from - Previous route
  • to - New route
  • duration - Navigation time in milliseconds
  • sessionId - Session identifier

Component Renders (hydratebeer_component_render)

Tracks performance of React components (when enabled).

PostHog Event:

{
  "event": "hydratebeer_component_render",
  "properties": {
    "componentName": "ProductList",
    "duration": 23.4,
    "phase": "update",
    "isSlow": true,
    "sessionId": "sess_xyz789...",
    "timestamp": "2025-01-06T10:30:02.000Z"
  },
  "distinct_id": "sess_xyz789...",
  "timestamp": "2025-01-06T10:30:02.000Z"
}

Captured Properties:

  • componentName - Name of the component
  • duration - Render time in milliseconds
  • phase - Render phase ('mount' or 'update')
  • isSlow - Boolean flag if duration exceeds 16ms threshold
  • sessionId - Session identifier

Component performance tracking uses React's Profiler API and can be disabled via trackComponentPerformance: false in config.

Errors (hydratebeer_error)

Automatically captures unhandled errors and exceptions (when enabled).

PostHog Event:

{
  "event": "hydratebeer_error",
  "properties": {
    "message": "Cannot read property 'foo' of undefined",
    "stack": "Error: Cannot read property...\n at Component...",
    "componentStack": "in ProductList\n in Page",
    "sessionId": "sess_xyz789...",
    "timestamp": "2025-01-06T10:30:03.000Z"
  },
  "distinct_id": "sess_xyz789...",
  "timestamp": "2025-01-06T10:30:03.000Z"
}

Captured Properties:

  • message - Error message
  • stack - Stack trace
  • componentStack - React component stack (if available)
  • sessionId - Session identifier

Session Start (hydratebeer_session_start)

Triggered when a new user session begins.

PostHog Event:

{
  "event": "hydratebeer_session_start",
  "properties": {
    "sessionId": "sess_xyz789...",
    "userAgent": "Mozilla/5.0...",
    "timestamp": "2025-01-06T10:30:00.000Z"
  },
  "distinct_id": "sess_xyz789...",
  "timestamp": "2025-01-06T10:30:00.000Z"
}

Captured Properties:

  • sessionId - Unique session identifier
  • userAgent - Browser user agent string
  • timestamp - Session start time

Manual Tracking

Use the useHydrateBeer hook to track custom events:

Custom Events (hydratebeer_custom)

Track application-specific business events:

'use client';

import { useHydrateBeer } from "hydrate-beer/react";

export default function CheckoutButton() {
  const { trackCustomEvent } = useHydrateBeer();

  const handleCheckout = async () => {
    const start = performance.now();
    await processCheckout();
    const duration = performance.now() - start;

    trackCustomEvent("checkout_completed", {
      duration,
      itemCount: 3,
      totalPrice: 99.99,
      paymentMethod: "stripe",
    });
  };

  return <button onClick={handleCheckout}>Checkout</button>;
}

PostHog Event:

{
  "event": "hydratebeer_custom",
  "properties": {
    "customEventName": "checkout_completed",
    "duration": 234,
    "itemCount": 3,
    "totalPrice": 99.99,
    "paymentMethod": "stripe",
    "sessionId": "sess_xyz789...",
    "timestamp": "2025-01-06T10:30:04.000Z"
  },
  "distinct_id": "sess_xyz789...",
  "timestamp": "2025-01-06T10:30:04.000Z"
}

All your custom properties are merged into the PostHog event properties, making them queryable in PostHog dashboards.

Error Tracking

Manually track errors with additional context:

'use client';

import { useHydrateBeer } from "hydrate-beer/react";

export default function DataFetcher() {
  const { trackError } = useHydrateBeer();

  const fetchData = async () => {
    try {
      await api.getData();
    } catch (error) {
      trackError(error as Error, {
        component: "DataFetcher",
        action: "fetchData",
        endpoint: "/api/data",
        retryCount: 3,
      });
    }
  };

  return <button onClick={fetchData}>Load Data</button>;
}

Session Information

Every event automatically includes:

PropertyTypeDescription
sessionIdstringAnonymous session UUID
timestampstringISO 8601 timestamp
distinct_idstringPostHog user identifier (uses sessionId)

Session ID Generation: Uses crypto.randomUUID() for secure, anonymous tracking. Sessions are ephemeral and not tied to user identity.

What Is NOT Tracked

HydrateBeer is privacy-focused and never collects:

  • User identity or personal information (PII)
  • Component props or state values
  • Form inputs or user-entered data
  • Cookies or authentication tokens
  • IP addresses (unless PostHog GeoIP is enabled)
  • Business logic or application data
  • Passwords or sensitive information
  • DOM content or screenshots

Privacy by Design: Only performance metrics and custom event names are collected.

Data Storage & Retention

  • PostHog Cloud - Data stored in PostHog's secure infrastructure
  • Retention - Based on your PostHog plan (typically 7 years on paid, 1 year on free)
  • GDPR Compliant - PostHog is GDPR and SOC 2 compliant
  • Data Export - Export your data anytime via PostHog API or UI
  • Data Deletion - Request data deletion through PostHog

PostHog automatically handles data retention, backups, and compliance. You don't need to manage any infrastructure.

Batching & Sending

Events are batched for network efficiency:

SettingDefaultDescription
batchSize10Max events before auto-send
flushInterval5000msAuto-send interval
Auto-flushAlwaysOn page unload via sendBeacon

Example Configuration:

<HydrateBeerProvider
  config={{
    posthogApiKey: process.env.NEXT_PUBLIC_HYDRATE_BEER_POSTHOG_API_KEY!,
    batchSize: 15,        // Send after 15 events
    flushInterval: 3000,  // Or every 3 seconds
  }}
>
  {children}
</HydrateBeerProvider>

How it works:

  • Events are sent when either batchSize is reached OR flushInterval passes
  • On page unload, all pending events are immediately sent
  • Failed sends are retried once

Metric Accuracy

  • API: performance.now()
  • Precision: ~0.1ms (sub-millisecond)
  • Measurement: Start of navigation to route change completion

Component Render Timing

  • API: React Profiler
  • Precision: Sub-millisecond
  • Includes: Render time + commit phase time

Custom Event Timing

  • API: performance.now() or Date.now()
  • Precision: Depends on your implementation
  • Best Practice: Use performance.now() for high-precision timing

Silent Failures

HydrateBeer is designed to never break your app:

  • Network errors caught and logged in debug mode
  • Invalid data silently discarded
  • SDK errors never throw to your application
  • All operations wrapped in try/catch
  • Failed sends logged but don't crash the app
  • PostHog API errors are gracefully handled

Philosophy: Analytics should enhance, not impair, user experience.

Debug Mode

Enable debug logging to see what's being tracked:

<HydrateBeerProvider
  config={{
    posthogApiKey: process.env.NEXT_PUBLIC_HYDRATE_BEER_POSTHOG_API_KEY!,
    debug: true,  // Enable debug logging
  }}
>
  {children}
</HydrateBeerProvider>

Console output:

HydrateBeer: Initialized successfully
HydrateBeer: Collected event hydratebeer_page_view { path: '/products' }
HydrateBeer: Flushing 10 events to PostHog
HydrateBeer: PostHog API response: 200 OK

Data Flow

React Component Render

SDK Event Collector (batches events)

Flush Trigger (every 5s or 10 events)

PostHog Batch API (/batch/)

PostHog Events Storage

    PostHog Dashboards & Insights

Viewing Your Data in PostHog### Navigate to Events

  1. Log in to your PostHog instance
  2. Go to ActivityEvents
  3. Filter by events starting with hydratebeer_

Create Insights

Average Navigation Time:

SELECT avg(properties.duration)
FROM events
WHERE event = 'hydratebeer_navigation'

Most Visited Pages:

SELECT properties.path, count()
FROM events
WHERE event = 'hydratebeer_page_view'
GROUP BY properties.path
ORDER BY count() DESC

Slow Component Renders:

SELECT properties.componentName, avg(properties.duration), count()
FROM events
WHERE event = 'hydratebeer_component_render'
  AND properties.isSlow = true
GROUP BY properties.componentName

Build Dashboards

Create custom dashboards in PostHog:

  • Performance Overview - Page load times, navigation speed
  • Error Tracking - Error rates by component
  • User Journey - Page flow and navigation paths
  • Component Health - Render performance by component

Event Name Reference

Event NameDescriptionAuto-Tracked
hydratebeer_page_viewPage navigationYes
hydratebeer_navigationRoute transitionYes
hydratebeer_component_renderComponent renderConfigurable
hydratebeer_errorError capturedConfigurable
hydratebeer_session_startSession startConfigurable
hydratebeer_customCustom eventsManual

Best Practices

1. Use Meaningful Event Names

// ✅ Good - Descriptive and actionable
trackCustomEvent('user_subscribed_premium', { plan: 'monthly' });
trackCustomEvent('product_added_to_cart', { productId: '123' });

// ❌ Bad - Too generic
trackCustomEvent('click');
trackCustomEvent('event');

2. Include Relevant Context

// ✅ Good - Rich context for analysis
trackCustomEvent('search_performed', {
  query: 'react hooks',
  resultsCount: 42,
  duration: 234,
  filters: ['recent', 'popular'],
});

// ❌ Bad - Missing useful context
trackCustomEvent('search');

3. Don't Over-Track

// ✅ Good - Business-critical events
trackCustomEvent('purchase_completed', { amount: 99.99 });

// ❌ Bad - Noisy, not actionable
trackCustomEvent('mouse_moved');
trackCustomEvent('scroll_event');

4. Handle Sensitive Data

// ✅ Good - No PII
trackCustomEvent('form_submitted', {
  formType: 'contact',
  fieldCount: 5,
});

// ❌ Bad - Contains PII
trackCustomEvent('form_submitted', {
  email: 'user@example.com',  // Don't track PII!
  name: 'John Doe',
});

Next Steps

On this page