juice_analytics

Event and screen tracking as a Juice bloc — fanned out to one or more sinks, behind a consent gate.

pub package License: MIT

What it owns

Consent state and tracking bookkeeping. It does not own a vendor SDK — each destination is an AnalyticsSink adapter (Firebase, Mixpanel, Segment, PostHog).

Install

dependencies:
  juice_analytics: ^0.2.0

Use

final analytics = AnalyticsBloc.withConfig(AnalyticsConfig(
  sinks: [
    MyFirebaseSink(),
    if (kDebugMode) ConsoleAnalyticsSink(),
  ],
  initiallyEnabled: false,   // require consent first
));

analytics.setConsent(true);
analytics.log('checkout_started', {'cart': 3});
analytics.screen('Cart');
analytics.setUser('u_123', {'plan': 'pro'});

Fan-out + isolation

Every call fans out to all sinks; a sink that throws is isolated so it can't break tracking for the others.

When consent is off, events are dropped and counted — never buffered. So granting consent later never flushes a backlog of pre-consent events.

analytics.setConsent(false); // events now drop (state.droppedCount climbs)

setUser still records the id in state for your UI, but only forwards identity to sinks with consent.

Writing a sink

class MyFirebaseSink implements AnalyticsSink {
  @override
  Future<void> logEvent(String name, Map<String, Object?> params) =>
      FirebaseAnalytics.instance.logEvent(name: name, parameters: params.cast());
  @override
  Future<void> setScreen(String name) =>
      FirebaseAnalytics.instance.logScreenView(screenName: name);
  // setUser / flush / dispose…
}

State

Field Meaning
enabled consent granted
userId / screenName current identity / screen
eventCount events forwarded this session
droppedCount events dropped for lack of consent

Rebuild groups: analytics:status, analytics:screen.

License

MIT License — see LICENSE.

Libraries

juice_analytics
Event and screen tracking as a Juice bloc, with a consent gate and a fan-out sink seam.