liquid_amplitude 0.2.0
liquid_amplitude: ^0.2.0 copied to clipboard
Amplitude destination for liquid_analytics — product analytics with user and group properties, EU residency, and opt-out.
liquid_amplitude #
Amplitude destination for
liquid_analytics — product analytics with user and
group properties, US/EU residency, and client-side opt-out.
Install #
dependencies:
liquid_analytics: ^0.2.0
liquid_amplitude: ^0.2.0
Use #
Let the sink construct Amplitude for you by passing an apiKey:
final liquid = Liquid(
sinks: [
AmplitudeSink(
apiKey: 'YOUR_API_KEY',
serverZone: ServerZone.eu, // optional residency
),
],
consent: ConsentPolicy(
requireOptIn: true,
map: {ConsentCategory.analytics: ['amplitude']},
),
);
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 Amplitude is already initialized elsewhere, inject the instance:
final amplitude = Amplitude(Configuration(apiKey: 'YOUR_API_KEY'));
await amplitude.isBuilt;
final liquid = Liquid(sinks: [AmplitudeSink(amplitude: amplitude)]);
Typed events (recommended) #
The string API above is the quick path. A typed event keeps the name and property keys in one place, so the same definition feeds both event properties and the user/group properties Amplitude builds from traits:
class CheckoutStarted extends LiquidEvent {
const CheckoutStarted({required this.cartValue, required this.items});
final double cartValue;
final List<String> items;
@override
String get name => 'checkout_started';
@override
Map<String, Object?> get properties => {
'cart_value': cartValue,
'items': items, // nested lists/maps reach Amplitude intact
};
}
liquid.log(const CheckoutStarted(cartValue: 42, items: ['sku_1', 'sku_2']));
Override category to route an event to a different consent bucket (e.g.
ConsentCategory.marketing). No build step is involved — these are plain
classes. To generate them from a YAML schema instead, see
liquid_codegen.
Message mapping #
| liquid message | Amplitude call |
|---|---|
track |
track(BaseEvent) |
screen |
track as Screen Viewed with a screen_name property |
identify |
setUserId + identify(Identify) per trait |
group |
setGroup + groupIdentify per trait |
reset |
reset |
Amplitude has no first-class alias API (identity is userId / deviceId), so
the sink does not advertise that capability and the client skips it.
Amplitude's group model uses a (groupType, groupName) pair. liquid's
single-id group('acme') maps groupName = 'acme' with the type set by
groupType ('company' by default):
AmplitudeSink(apiKey: '…', groupType: 'organization');
Property handling #
Amplitude accepts nested objects, lists, booleans and numbers.
AmplitudePropertyMapper therefore only:
- drops
nullvalues, and - converts
DateTime(to ISO-8601) andEnum(to.name) recursively.
Opt-out bridge #
Optionally mirror liquid's consent into Amplitude's client-side opt-out so the SDK itself stops sending when the user denies analytics:
final amplitudeSink = AmplitudeSink(apiKey: '…');
final liquid = Liquid(sinks: [amplitudeSink]);
liquid.consent.addListener(() {
amplitudeSink.applyConsent(
granted: liquid.consent.statusOf(ConsentCategory.analytics) ==
ConsentStatus.granted,
);
});
Testing #
AmplitudePropertyMapper is a pure transform and is unit-tested without a live
project. For end-to-end checks, run against an Amplitude project and inspect
User Lookup / the event stream.