Feature SDKs (Pro)
app_debugger_analytics Pro
- Tier
- Proversion 1.3.4
- Command
archipelago generate app_debugger_analytics- Generates
features/app_debugger_analytics/app_debugger_analyticsfeatures/app_debugger_analytics/app_debugger_analytics_apifeatures/app_debugger_analytics/app_debugger_analytics_noop
- Generates first
- app_debuggerwhen needed and missing, so there is nothing to install first
- Depends on
- shared_consent, shared_identifiers, analytics_sdkgenerate these first
Analytics event inspector sub-brick for
app_debugger. Adds an Analytics tool to the debugger that captures everyTrackDataevent flowing through theAnalyticInterceptorchain, plus a consent-status banner so a build's consent state is never mistaken for "nothing is being tracked". Automatically swapped to a no-op stub in production-flavor builds viabuild_prepare.yaml.
Variables
This brick has no generation-time variables.
Prerequisites
app_debuggeris generated first when the project lacks it. It provides thearchipelago:debug_panel_pagessentinel; see Wiring below for where it lives).analytics_sdkmust already be generated (providesanalytics_api, which this brick's hook adds toapp_debugger— notanalytics_impl, since a debug-only package must not pull in a release impl).
Usage
Interactive
archipelago generate app_debugger_analyticsNon-interactive (CI)
archipelago generate app_debugger_analytics --config my_config.jsonPublic API
AnalyticsInspectorSDK (in app_debugger_analytics_api) is the contract both the debug impl and the noop stub implement:
abstract interface class AnalyticsInspectorSDK() implements FeatureSDK {
bool get isActive;
Stream<AnalyticsCaptureEntry> get captureStream;
List<AnalyticsCaptureEntry> get currentEntries;
void clearCapture();
AnalyticInterceptor? get interceptor;
}interceptor returns null in the noop stub, so callers must null-guard before registering it (see wiring below).
Generated Structure
features/
└── app_debugger_analytics/
├── app_debugger_analytics_api/
│ └── lib/src/
│ ├── analytics_inspector_sdk.dart # AnalyticsInspectorSDK contract
│ └── models/
│ ├── analytics_capture_entry.dart
│ └── analytics_inspector_config.dart
├── app_debugger_analytics/
│ └── lib/src/
│ ├── analytics_debugger_interceptor.dart
│ ├── analytics_inspector_page.dart
│ ├── analytics_inspector_sdk_impl.dart
│ ├── consent_status_banner.dart # Explains why the tool may look empty
│ └── di/
└── app_debugger_analytics_noop/
└── lib/src/
└── di/Wiring (Auto-Patched by post_gen.dart)
On a current project both patches below land in features/app_debugger/app_debugger/lib/src/di/debug_tools.dart. The marker moved between app_debugger versions, so the hook uses the first file that has it: app_debugger's lib/src/di/debug_tools.dart (2.0.0 and later), its lib/src/app_debugger_sdk_impl.dart (1.3.0 to 1.15.x), then the app's lib/bootstrap.dart (older), and adds the imports and path dependencies to that package. A file that already resolves the SDK is left as it is. If no file has the marker, pre_gen prints the lines to add and stops before it writes any file.
di/debug_tools.dart — eager resolution
// archipelago:debug_panel_pages:start
GetIt.I<AnalyticsInspectorSDK>();
// archipelago:debug_panel_pages:enddi/debug_tools.dart — interceptor registration
// archipelago:analytics_inspector_interceptor:start
final analyticsInterceptor = GetIt.I<AnalyticsInspectorSDK>().interceptor;
if (analyticsInterceptor != null) {
AnalyticInterceptorRegistry.instance.register(analyticsInterceptor);
}
// archipelago:analytics_inspector_interceptor:endapp_debugger only depends on analytics_api for this (not analytics_impl) — the registry lives in analytics_api, and analytics_impl reads it on every tracked call, so the interceptor applies whenever it registers.
post_launch_initializer.dart — AnalyticsInitializer.initialize()
The hook also injects a _AnalyticsPostLaunchInitializer class plus an archipelago:analytics_initializer sentinel into the app's post_launch_initializer.dart, so AnalyticsInitializer.initialize(getIt) actually runs (starting vendors behind whatever interceptors are already queued) — it is idempotent and skipped if that sentinel is already present. If the app doesn't have lib/host/initializers/post_launch_initializer.dart yet, this step is skipped and a warning is logged.
If any of these patches can't find their target (e.g. a hand-edited app_debugger without the marker), add them manually — the hook logs a warning naming exactly which sentinel is missing.
Consent Awareness
ConsentStatusBanner (from consent_api) is rendered above the captured-events list. A consent interceptor sits ahead of the debugger's own interceptor in the chain, so when a purpose is denied, events never reach the inspector — the tool would otherwise look identical to "nothing is being tracked". The banner reads the ambient ConsentGateRegistry.instance.gate and shows one of three states: granted, denied, or forced (when a decision carries ConsentSource.debugOverride, e.g. via the CONSENT_DEBUG_GRANT_ALL dart-define) — a forced grant is always visually distinct from real user consent.
Interceptor Chain Semantics
The AnalyticsDebuggerInterceptor is purely observational — it never drops events. intercept() always calls chain.proceed(data) and returns the result. Adding this interceptor has no side-effects on your analytics pipeline.
The onSetUserId and onReset hooks track the current user ID so captured entries carry the user context at the time of the event.
build_prepare Swap
- debug: app_debugger_analytics
release: app_debugger_analytics_noopChangelog
Run archipelago brick info app_debugger_analytics to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.