liquid_mixpanel 0.1.0
liquid_mixpanel: ^0.1.0 copied to clipboard
Mixpanel destination for liquid_analytics — product analytics with People and Group profiles, EU residency, and built-in opt-out.
liquid_mixpanel #
Mixpanel destination for
liquid_analytics — product analytics with People
profiles, Group Analytics, EU/India residency, and client-side opt-out.
Install #
dependencies:
liquid_analytics: ^0.1.0
liquid_mixpanel: ^0.1.0
Use #
Let the sink configure Mixpanel for you by passing a project token:
final liquid = Liquid(
sinks: [
MixpanelSink(
token: 'YOUR_PROJECT_TOKEN',
serverURL: 'https://api-eu.mixpanel.com', // optional residency / proxy
trackAutomaticEvents: false,
),
],
consent: ConsentPolicy(
requireOptIn: true,
map: {ConsentCategory.analytics: ['mixpanel']},
),
);
await liquid.init();
liquid.track('checkout_started', {
'cart_value': 42.0,
'is_gift': true,
'items': ['sku_1', 'sku_2'],
});
liquid.consent.grant(ConsentCategory.analytics);
If Mixpanel is already initialized elsewhere, inject the instance:
final mixpanel = await Mixpanel.init(
'YOUR_PROJECT_TOKEN',
trackAutomaticEvents: false,
);
final liquid = Liquid(sinks: [MixpanelSink(mixpanel: mixpanel)]);
Message mapping #
| liquid message | Mixpanel call |
|---|---|
track |
track |
screen |
track as Screen Viewed with a screen_name property |
identify |
identify + People.set per trait |
group |
setGroup + MixpanelGroup.set per trait |
alias |
alias(alias, currentDistinctId) |
reset |
reset |
Mixpanel's group model uses a (groupKey, groupID) pair. liquid's single-id
group('acme') maps groupID = 'acme' with the key set by groupKey
('company' by default):
MixpanelSink(token: '…', groupKey: 'organization');
Screen mapping is configurable if you prefer a different event shape:
MixpanelSink(
token: '…',
screenEventName: 'Viewed Screen',
screenNameProperty: 'name',
);
Property handling #
Mixpanel accepts nested objects, lists, booleans and numbers. MixpanelPropertyMapper
therefore only:
- drops
nullvalues, and - converts
DateTime(to ISO-8601) andEnum(to.name) recursively.
Group Analytics is the exception: MixpanelGroup.set only accepts string
values, so group traits are coerced to strings after conversion.
Opt-out bridge #
Optionally mirror liquid's consent into Mixpanel's client-side opt-out so the SDK itself stops sending when the user denies analytics:
final mixpanelSink = MixpanelSink(token: '…');
final liquid = Liquid(sinks: [mixpanelSink]);
liquid.consent.addListener(() {
mixpanelSink.applyConsent(
granted: liquid.consent.statusOf(ConsentCategory.analytics) ==
ConsentStatus.granted,
);
});
Testing #
MixpanelPropertyMapper is a pure transform and is unit-tested without a live
project. For end-to-end checks, run against a Mixpanel project and inspect the
Live View.