liquid_firebase 0.1.0
liquid_firebase: ^0.1.0 copied to clipboard
Firebase Analytics (Google Analytics for Firebase / GA4) destination for liquid_analytics.
liquid_firebase #
Firebase Analytics (Google Analytics for Firebase / GA4) destination for
liquid_analytics.
Install #
dependencies:
liquid_analytics: ^0.1.0
liquid_firebase: ^0.1.0
firebase_core: ^3.0.0
Use #
Initialize Firebase, then add FirebaseSink to your Liquid client:
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
final liquid = Liquid(
sinks: [FirebaseSink()],
consent: ConsentPolicy(
requireOptIn: true,
map: {ConsentCategory.analytics: ['firebase']},
),
);
await liquid.init();
liquid.track('checkout_started', {'cart_value': 42.0, 'is_gift': true});
liquid.consent.grant(ConsentCategory.analytics);
Message mapping #
| liquid message | Firebase call |
|---|---|
track |
logEvent |
screen |
logScreenView |
identify |
setUserId + setUserProperty per trait |
reset |
resetAnalyticsData |
Firebase has no group or alias concept, so those are ignored and the sink
does not advertise those capabilities (the client skips it for them).
Automatic sanitization #
Firebase rejects data that liquid's Map<String, Object?> allows: parameter
values must be a String or a number, names must be alphanumeric/underscore and
start with a letter, and there are length and count limits. FirebaseEventMapper
enforces all of this so events are never silently dropped by the native layer:
- Illegal name characters become underscores; names are truncated to 40 chars (24 for user properties) and forced to start with a letter.
- Booleans are encoded as
1/0(configurable), enums by.name,DateTimeas ISO-8601. Nested lists/maps are dropped. - String values are truncated to 100 chars; parameters are capped at 25.
Tune it by passing your own mapper:
FirebaseSink(mapper: const FirebaseEventMapper(boolsAsInts: false));
Firebase Consent Mode #
Optionally mirror liquid's consent into Firebase Consent Mode so Firebase itself honors the user's choice:
final firebaseSink = FirebaseSink();
final liquid = Liquid(sinks: [firebaseSink]);
liquid.consent.addListener(() {
firebaseSink.applyConsent(
analyticsGranted: liquid.consent.statusOf(ConsentCategory.analytics) ==
ConsentStatus.granted,
adsGranted: liquid.consent.statusOf(ConsentCategory.marketing) ==
ConsentStatus.granted,
);
});
Testing #
The sanitization logic lives in the pure FirebaseEventMapper, which is unit-
testable without a configured Firebase app. For end-to-end verification, run
your app against a real Firebase project and inspect DebugView.