Overview Przegląd
The Session Recording module captures user interactions inside your Android app — touches, screen transitions, scroll events, text input (always masked for privacy), gestures, optional view hierarchy snapshots, and analytics events (purchase, screen_view, ad_impression, etc.) from the Analytics module. Collected data is sent to a backend of your choice. Moduł Session Recording przechwytuje interakcje użytkowników wewnątrz aplikacji Android — dotknięcia, przejścia między ekranami, eventy scrolli, input tekstowy (zawsze maskowany dla prywatności), gesty, opcjonalne snapshoty hierarchii widoków oraz eventy analityczne (purchase, screen_view, ad_impression itp.) z modułu Analytics. Zebrane dane są wysyłane do wybranego backendu.
Two backend strategies are provided out of the box: Dwie strategie backendu dostępne od razu:
- Firebase Firestore — stores sessions directly in your Firebase projectprzechowuje sesje bezpośrednio w Twoim projekcie Firebase
- WordPress REST API — sends data to a WordPress site with the included pluginwysyła dane do strony WordPress za pomocą dołączonego pluginu
⚙️ How Recording WorksJak działa nagrywanie
Session Recording works on an event-stream basis — it does NOT take screenshots or record video. Instead, it captures a stream of structured JSON events describing every user interaction. This approach is: Session Recording działa na zasadzie strumienia eventów — NIE robi screenshotów ani nie nagrywa wideo. Zamiast tego przechwytuje strumień ustrukturyzowanych eventów JSON opisujących każdą interakcję użytkownika. Takie podejście jest:
- 🔒 Privacy-firstPrywatność przede wszystkim — no pixel data, no screenshots, text always maskedbrak danych pikselowych, brak screenshotów, tekst zawsze maskowany
- 📦 LightweightLekkie — JSON events are tiny compared to images/videoeventy JSON są małe w porównaniu do obrazów/wideo
- 📡 Low bandwidthNiskie zużycie pasma — events sent in compressed batches every 30seventy wysyłane w skompresowanych batchach co 30s
What IS collected:Co JEST zbierane:
[12:34:01] 👆 touch (423, 891) DOWN on "DemoActivity"
[12:34:01] 👆 touch (423, 891) UP on "DemoActivity"
[12:34:03] 🔄 screen_transition: DemoActivity → SettingsActivity
[12:34:05] 📜 scroll: (0, 340) on "SettingsActivity"
[12:34:08] ⌨️ text_input: [email_field] len=15 "•••••••••••••••"
[12:34:10] 🌳 view_hierarchy: { JSON tree with bounds }
[12:34:10] 📸 screenshot: JPEG 540x1200 (~40KB)
[12:34:12] 📊 analytics: "purchase" {product_id=premium, price=9.99, currency=USD}
[12:34:15] 📊 analytics: "screen_view" {screen_name=SettingsActivity}
What is NOT collected:Co NIE jest zbierane:
- ❌ Video (no screen recording / MediaProjection)Wideo (brak nagrywania ekranu / MediaProjection)
- ❌ Text content (always replaced with
•)Treść tekstowa (zawsze zastępowana znakiem•)
⚠️ Screenshot privacy: When captureScreenshots = true, actual JPEG
screenshots are captured from the device screen. Make sure to add sensitive screens (login, payment)
to excludedActivities. Screenshots use low quality + downscaling for small size.
⚠️ Prywatność screenshotów: Gdy captureScreenshots = true, rzeczywiste
screenshoty JPEG są przechwytywane z ekranu urządzenia. Pamiętaj, aby dodać wrażliwe ekrany (logowanie, płatności)
do excludedActivities. Screenshoty używają niskiej jakości + zmniejszonej rozdzielczości.
🔥 Firebase Firestore — data formatformat danych
Events are stored as raw JSON documents. Firestore acts as a pure data store — there is no built-in visual replay. You can query events via the Firebase console or build your own viewer. Eventy są przechowywane jako surowe dokumenty JSON. Firestore działa jako czysty magazyn danych — nie ma wbudowanego wizualnego odtwarzacza. Możesz przeszukiwać eventy przez konsolę Firebase lub zbudować własny viewer.
session_recordings/
{sessionId}/ ← document (session metadata)
sessionId: "abc-123-def"
userId: "user-456"
deviceInfo: '{"manufacturer":"Samsung","model":"S24",...}'
status: "completed"
startTimestamp: 1710000000000
endTimestamp: 1710001800000
batches/ ← subcollection
batch_0/ ← ~30 seconds of events
events: [
'{"type":"touch","x":423,"y":891,"action":"DOWN",...}',
'{"type":"screen_transition","from":"Demo","to":"Settings",...}',
'{"type":"analytics","eventName":"purchase","params":{"product_id":"premium","price":"9.99"},...}'
]
eventCount: 42
batchTimestamp: 1710000030000
batch_1/
events: [...]
Each event in the events array is a JSON string with type,
timestamp, screen, and type-specific fields (x/y for touch,
from/to for transitions, etc.).
Każdy event w tablicy events to string JSON z polami type,
timestamp, screen i polami specyficznymi dla typu (x/y dla dotyku,
from/to dla przejść, itd.).
🌐 WordPress — visual replay playerwizualny odtwarzacz sesji
The WordPress plugin provides a visual replay player in the admin panel: Plugin WordPress zapewnia wizualny odtwarzacz sesji w panelu admina:
- Canvas-based replayOdtwarzacz oparty na Canvas — draws a phone screen outline and animates touch events in real-time (red circles = taps, blue trails = finger movement, screen transitions)rysuje zarys ekranu telefonu i animuje eventy dotyku w czasie rzeczywistym (czerwone kółka = tapnięcia, niebieskie ślady = ruch palca, przejścia ekranów)
- 📸 Screenshot modeTryb screenshotów — when
captureScreenshots = true, actual JPEG screenshots are displayed as background with touch events overlaid on topgdycaptureScreenshots = true, rzeczywiste screenshoty JPEG wyświetlane są jako tło z nałożonymi eventami dotyku - 🏗 Wireframe modeTryb wireframe — when
captureViewHierarchy = true, reconstructs the screen layout as colored rectangles (buttons, text views, images) from the view tree datagdycaptureViewHierarchy = true, rekonstruuje układ ekranu jako kolorowe prostokąty (przyciski, pola tekstowe, obrazki) na podstawie danych drzewa widoków - Heatmap — aggregated visualization of all touch-down points (warm colors indicate high-tap areas)zagregowana wizualizacja wszystkich punktów dotyku (ciepłe kolory oznaczają obszary z dużą liczbą tapnięć)
- Interactive timelineInteraktywna oś czasu — click any event to jump to that moment in the replay; filterable by event typekliknij dowolny event, aby przeskoczyć do tego momentu w odtwarzaniu; filtrowanie po typie eventu
- Playback controlsKontrolki odtwarzania — play/pause, speedprędkość (0.5x — 10x), seek bar, restart
- Session statisticsStatystyki sesji — event counts by type, events per screen, analytics events breakdownliczba eventów wg typu, eventy na ekran, podsumowanie eventów analitycznych
- 📊 Analytics events overlayOverlay eventów analitycznych — when
captureAnalyticsEvents = true, analytics events (purchase, ad_impression, etc.) are shown as animated banners on the replay canvas and listed in the filterable timelinegdycaptureAnalyticsEvents = true, eventy analityczne (purchase, ad_impression itp.) wyświetlane są jako animowane bannery na canvasie odtwarzacza i widoczne w filtrowalnej osi czasu
The display mode can be toggled between Screenshot, Wireframe, and None (plain overlay). Screenshots are stored as JPEG files on the WordPress server, not in the database, for efficient storage and retrieval. Tryb wyświetlania można przełączać między Screenshot, Wireframe i None (prosty overlay). Screenshoty są przechowywane jako pliki JPEG na serwerze WordPress, nie w bazie danych, co zapewnia wydajne przechowywanie i pobieranie.
Quick StartSzybki start
// 1. In Application.onCreate(), after ADict.init():
// Choose a backend strategy:
ADict.SessionRecording.setBackendStrategy(
FirebaseSessionStrategy()
)
// 2. (Optional) Configure recording:
ADict.SessionRecording.configure(
SessionRecordingConfig(
samplingRate = 0.5f, // record 50% of sessions
captureTouch = true,
captureScroll = true,
captureTextInput = true,
maskAllTextInputs = true,
captureAnalyticsEvents = true // capture Analytics events (purchase, screen_view, etc.)
)
)
// 3. Start recording:
ADict.SessionRecording.startSession()
// 4. (Optional) Set user ID:
ADict.SessionRecording.setUserId("user-123")
ConfigurationKonfiguracja
SessionRecordingConfig(
enabled = true, // master switch
samplingRate = 1.0f, // 0.0–1.0 (1.0 = record all sessions)
samplingStrategy = SamplingStrategy.PER_SESSION, // PER_SESSION or PER_INSTALL
maxSessionDurationMs = 30 * 60 * 1000L, // auto-stop after 30 min
flushIntervalMs = 30_000L, // send events every 30s
maxBufferSize = 500, // force flush when buffer reaches 500
captureTouch = true, // track touch events
captureScroll = true, // track scroll events
captureScreenTransitions = true, // track Activity transitions
captureTextInput = true, // track text input (masked)
maskAllTextInputs = true, // replace text with '•' chars
captureViewHierarchy = false, // periodic view hierarchy snapshots
viewHierarchyIntervalMs = 5_000L, // snapshot every 5s
captureScreenshots = false, // periodic JPEG screenshots (WordPress only)
screenshotIntervalMs = 2_000L, // screenshot every 2s
screenshotQuality = 40, // JPEG quality 0-100 (40 = good balance)
screenshotMaxWidth = 540, // ⭐ adaptive: target max width in px (0 = use fixed screenshotScale)
captureAnalyticsEvents = true, // capture events from Analytics module
redactedAnalyticsParamKeys = setOf(// mask sensitive analytics params
"user_id", "email"
),
maxAnalyticsParamsLength = 500, // max chars for serialized params (0 = unlimited)
excludedActivities = setOf( // skip these Activities
"SettingsActivity",
"LoginActivity"
),
excludedViewIds = setOf( // skip these views (privacy)
R.id.password_field,
R.id.credit_card_input
)
)
| ParameterParametr | TypeTyp | DefaultDomyślna | DescriptionOpis |
|---|---|---|---|
enabled |
Boolean | true | Master on/off switchGłówny przełącznik wł/wył |
samplingRate |
Float | 1.0 | Percentage of sessions to record (0.0–1.0)Procent nagrywanych sesji (0.0–1.0) |
samplingStrategy |
SamplingStrategy | PER_SESSION |
PER_SESSION — independent random draw per startSession() call (default, backward-compatible).PER_INSTALL — deterministic per app install. Same device is always recorded (or not) for a given rate. Increasing the rate always adds users, never removes already-included ones. Recommended for production.
PER_SESSION — niezależny losowy rzut per wywołanie startSession() (domyślne, wstecznie kompatybilne).PER_INSTALL — deterministyczne per instalację aplikacji. To samo urządzenie jest zawsze nagrywane (lub nie) dla danego rate. Podniesienie rate zawsze dodaje użytkowników, nigdy nie usuwa już włączonych. Rekomendowane dla produkcji.
|
forceSampling |
Boolean | false |
⚠️ Debug only. When true, bypasses samplingRate and samplingStrategy entirely — always records.
Useful for testing with PER_INSTALL when your device happens to fall outside the sampling group.
⚠️ Tylko do testów. Gdy true, pomija samplingRate i samplingStrategy — zawsze nagrywa.
Przydatne przy testowaniu z PER_INSTALL, gdy Twoje urządzenie wypadło poza grupę próby.
|
maxSessionDurationMs |
Long | 1800000 | Auto-stop after this durationAutomatyczne zatrzymanie po tym czasie |
flushIntervalMs |
Long | 30000 | How often to send buffered eventsJak często wysyłać buforowane eventy |
maxBufferSize |
Int | 500 | Force flush when buffer reaches this sizeWymuś wysłanie gdy bufor osiągnie ten rozmiar |
captureTouch |
Boolean | true | Record touch events (x, y, action)Nagrywaj eventy dotyku (x, y, akcja) |
captureScroll |
Boolean | true | Record scroll eventsNagrywaj eventy scrolli |
captureScreenTransitions |
Boolean | true | Record Activity transitionsNagrywaj przejścia między Activity |
captureTextInput |
Boolean | true | Record text input (always masked)Nagrywaj input tekstowy (zawsze maskowany) |
maskAllTextInputs |
Boolean | true | Replace all text chars with '•'Zastąp wszystkie znaki tekstu znakiem '•' |
captureViewHierarchy |
Boolean | false | Periodic view tree snapshots (wireframe mode in replay)Okresowe snapshoty drzewa widoków (tryb wireframe w odtwarzaczu) |
captureScreenshots |
Boolean | false | Periodic JPEG screenshots (actual screen capture)Okresowe screenshoty JPEG (rzeczywiste przechwytywanie ekranu) |
screenshotIntervalMs |
Long | 2000 | Screenshot capture interval in msInterwał przechwytywania screenshotów w ms |
screenshotQuality |
Int | 40 | JPEG quality 0–100 (lower = smaller files)Jakość JPEG 0–100 (niższa = mniejsze pliki) |
screenshotScale |
Float | 0.5 | Fixed resolution scale factor 0.0–1.0. Ignored when screenshotMaxWidth > 0.Stały współczynnik skali 0.0–1.0. Ignorowany gdy screenshotMaxWidth > 0. |
screenshotMaxWidth |
Int | 540 |
⭐ Adaptive scaling — target max width in pixels. When > 0, scale is computed dynamically:
min(maxWidth / screenWidth, 1.0). Produces consistent JPEG sizes regardless of device resolution.
Recommended over screenshotScale. Use ScreenshotPreset for ready-made presets.
Set to 0 to disable (uses fixed screenshotScale instead).
⭐ Adaptacyjne skalowanie — docelowa max szerokość w pikselach. Gdy > 0, skala obliczana dynamicznie:
min(maxWidth / screenWidth, 1.0). Daje spójne rozmiary JPEG niezależnie od rozdzielczości urządzenia.
Rekomendowane zamiast screenshotScale. Użyj ScreenshotPreset po gotowe presety.
Ustaw 0 aby wyłączyć (wtedy obowiązuje stały screenshotScale).
|
captureAnalyticsEvents |
Boolean | true | Capture events from the Analytics module (purchase, screen_view, ad_impression, etc.). When enabled, a SessionRecordingAnalyticsProvider is auto-registered as an Analytics provider during recording.Przechwytuj eventy z modułu Analytics (purchase, screen_view, ad_impression itp.). Gdy włączone, SessionRecordingAnalyticsProvider jest automatycznie rejestrowany jako provider Analytics podczas nagrywania. |
redactedAnalyticsParamKeys |
Set<String> | emptySet() | Analytics event parameter keys to mask (values replaced with "***"). Use for sensitive data like "email", "user_id".Klucze parametrów eventów analitycznych do maskowania (wartości zastępowane "***"). Używaj dla danych wrażliwych jak "email", "user_id". |
maxAnalyticsParamsLength |
Int | 500 | Maximum total character length for serialized analytics params. Prevents oversized events. 0 = no limit.Maksymalna łączna długość znaków serializowanych parametrów analytics. Zapobiega nadmiernie dużym eventom. 0 = bez limitu. |
rcKeyEnabled |
String | "session_recording_enabled" |
Remote Config key (Boolean) that disables recording when set to falseKlucz Remote Config (Boolean) wyłączający nagrywanie gdy ustawiony na false |
rcKeySamplingRate |
String | "session_recording_sampling_rate" |
Remote Config key (Double 0.0–1.0) overriding samplingRate. Value -1.0 = use code valueKlucz Remote Config (Double 0.0–1.0) nadpisujący samplingRate. Wartość -1.0 = użyj wartości z kodu |
Backend StrategiesStrategie backendu
🔥 Firebase Firestore
// Basic usage — stores in "session_recordings" collection
ADict.SessionRecording.setBackendStrategy(
FirebaseSessionStrategy()
)
// Custom collection name
val strategy = FirebaseSessionStrategy()
strategy.configure(mapOf(
"collectionName" to "my_app_sessions"
))
ADict.SessionRecording.setBackendStrategy(strategy)
Firestore structure:Struktura Firestore:
session_recordings/
{sessionId}/
sessionId: "abc-123"
userId: "user-456"
deviceInfo: "{...}"
startTimestamp: 1710000000000
status: "completed"
batches/
batch_0/
events: [ "{...}", "{...}", ... ]
eventCount: 42
batchTimestamp: 1710000030000
Requirements:Wymagania:
google-services.jsonconfigured in your appskonfigurowany w aplikacji- Firebase Firestore SDK (included with ADictdołączony z ADict)
- Firestore security rules allowing writesReguły bezpieczeństwa Firestore pozwalające na zapis
🌐 WordPress REST API
ADict.SessionRecording.setBackendStrategy(
WordPressSessionStrategy(
siteUrl = "https://your-site.com",
apiKey = "your-api-key-from-wp-admin"
)
)
// With custom settings
val strategy = WordPressSessionStrategy()
strategy.configure(mapOf(
"siteUrl" to "https://your-site.com",
"apiKey" to "your-api-key",
"connectTimeoutMs" to 10000,
"readTimeoutMs" to 20000,
"maxRetries" to 5
))
ADict.SessionRecording.setBackendStrategy(strategy)
WordPress plugin setup:Konfiguracja pluginu WordPress:
- Copy
wordpress-plugin/adict-session-recording/to/wp-content/plugins/Skopiujwordpress-plugin/adict-session-recording/do/wp-content/plugins/ - Activate the plugin in WP AdminAktywuj plugin w panelu WP Admin
- Go to "Session Recording → Settings" to get your API keyPrzejdź do "Session Recording → Settings" aby uzyskać klucz API
- Use the API key in your Android app configurationUżyj klucza API w konfiguracji aplikacji Android
REST endpoints:Endpointy REST:
| MethodMetoda | Endpoint | AuthAutoryzacja | DescriptionOpis |
|---|---|---|---|
| POST | /wp-json/adict/v1/session-events | API Key | Receive event batchOdbierz batch eventów |
| POST | /wp-json/adict/v1/session-end | API Key | End sessionZakończ sesję |
| GET | /wp-json/adict/v1/sessions | Admin | List sessionsLista sesji |
| GET | /wp-json/adict/v1/sessions/{id} | Admin | Session detailsSzczegóły sesji |
| DELETE | /wp-json/adict/v1/sessions/{id} | Admin | Delete sessionUsuń sesję |
Event TypesTypy eventów
| TypeTyp | DescriptionOpis | DataDane |
|---|---|---|
TouchEvent |
Touch on screenDotknięcie ekranu | x, y, action (DOWN/MOVE/UP/CANCEL) |
ScrollEvent |
Scroll changeZmiana scrolla | viewId, scrollX, scrollY |
ScreenTransitionEvent |
Activity changeZmiana Activity | fromScreen, toScreen |
TextInputEvent |
Text field inputInput w pole tekstowe | viewId, textLength, maskedText (•••) |
GestureEvent |
Swipe, pinch, etc.Swipe, pinch, itd. | gestureType, start/end coordinates |
ViewHierarchySnapshot |
View tree snapshotSnapshot drzewa widoków | JSON tree (class, bounds, visibility — no text content)Drzewo JSON (klasa, wymiary, widoczność — bez treści tekstowej) |
LifecycleEvent |
App lifecycleCykl życia aplikacji | state (resumed, paused, created, destroyed) |
ScreenshotEvent |
Screen capture (JPEG)Zrzut ekranu (JPEG) | imageBase64, width, height |
AnalyticsEvent |
Analytics event from Analytics moduleEvent analityczny z modułu Analytics | eventName, params (Map<String, Any?>) |
Session ControlKontrola sesji
// Start recording
ADict.SessionRecording.startSession()
// Pause (e.g., when app goes to background)
ADict.SessionRecording.pauseSession()
// Resume
ADict.SessionRecording.resumeSession()
// Stop recording
ADict.SessionRecording.stopSession()
// Get current session ID
val sessionId = ADict.SessionRecording.currentSessionId
// Get event count
val count = ADict.SessionRecording.eventCount
// Observe recording status (StateFlow)
lifecycleScope.launch {
ADict.SessionRecording.status.collect { status ->
when (status) {
RecordingStatus.IDLE -> { /* not recording */ }
RecordingStatus.RECORDING -> { /* actively recording */ }
RecordingStatus.PAUSED -> { /* paused */ }
RecordingStatus.STOPPED -> { /* stopping, flushing */ }
}
}
}
🎲 Sampling Rate & Strategy
The samplingRate parameter controls what percentage of sessions are recorded.
The samplingStrategy parameter controls how the decision is made.
Parametr samplingRate kontroluje jaki procent sesji jest nagrywanych.
Parametr samplingStrategy kontroluje jak podejmowana jest decyzja.
🔀 PER_SESSION (defaultdomyślna)
Each startSession() call is an independent random draw.
At samplingRate = 0.5, each session has a 50% chance of being recorded.
The same user may be recorded in one session and skipped in the next.
Only converges to the target percentage over a large number of sessions.
Każde wywołanie startSession() to niezależny losowy rzut.
Przy samplingRate = 0.5 każda sesja ma 50% szans na nagranie.
Ten sam użytkownik może być nagrywany w jednej sesji, a pominięty w następnej.
Procent zbliża się do docelowego dopiero przy dużej liczbie sesji.
// Random per session (backward-compatible default)
ADict.SessionRecording.configure(
SessionRecordingConfig(
samplingRate = 0.1f,
samplingStrategy = SamplingStrategy.PER_SESSION
)
)
📌 PER_INSTALL (recommended for productionrekomendowana dla produkcji)
The decision is deterministic per app install — based on a stable installation ID
(UUID generated once and stored in SharedPreferences). The same device always
gets the same result for a given samplingRate.
Decyzja jest deterministyczna per instalację aplikacji — oparta na stabilnym
identyfikatorze instalacji (UUID generowany raz i przechowywany w SharedPreferences).
To samo urządzenie zawsze dostaje ten sam wynik dla danego samplingRate.
Key property: increasing the rate always adds users,
never removes already-included ones. If a device is recorded at rate=0.1,
it will also be recorded at rate=0.5 and rate=1.0.
Kluczowa właściwość: podniesienie rate zawsze dodaje użytkowników,
nigdy nie usuwa już włączonych. Jeśli urządzenie jest nagrywane przy rate=0.1,
będzie nagrywane też przy rate=0.5 i rate=1.0.
// Deterministic per install (recommended for production)
ADict.SessionRecording.configure(
SessionRecordingConfig(
samplingRate = 0.1f,
samplingStrategy = SamplingStrategy.PER_INSTALL
)
)
// Same device → always the same decision (recorded or not)
// Increasing rate: 0.1 → 0.5 → only ADDS users, never removes
// Disable recording entirely
ADict.SessionRecording.configure(
SessionRecordingConfig(enabled = false)
)
ComparisonPorównanie
| PER_SESSION | PER_INSTALL ⭐ | |
|---|---|---|
| DecisionDecyzja | Math.random() < rate |
hash(installId) < rate |
| Same user, different sessionsTen sam user, różne sesje | May varyMoże się zmieniać | Always the sameZawsze tak samo |
| Rate increase effectEfekt podwyższenia rate | UnpredictableNieprzewidywalny | Only adds users (⊂ nesting)Tylko dodaje userów (⊂ zagnieżdżanie) |
| Small sample accuracyDokładność na małej próbie | Poor (variance)Słaba (wariancja) | Perfect (deterministic)Idealna (deterministyczna) |
| Use casePrzypadek użycia | Testing, backward compatTestowanie, wsteczna kompatybilność | ProductionProdukcja |
| Sampling Rate | Sessions RecordedNagrywane sesje | Recommended ForRekomendowane dla |
|---|---|---|
| 1.0 | 100% | Development, Testing |
| 0.5 | 50% | Beta testing |
| 0.1 | 10% | Production |
| 0.01 | 1% | High-traffic production |
🔧 Remote Config IntegrationIntegracja z Remote Config
When Firebase Remote Config is configured in your app (ADict.Config.remoteConfig),
Session Recording automatically reads two RC keys that can override the values set in code —
without a new app release.
Gdy Firebase Remote Config jest skonfigurowany w aplikacji (ADict.Config.remoteConfig),
Session Recording automatycznie odczytuje dwa klucze RC, które mogą nadpisać wartości ustawione w kodzie —
bez nowego wydania aplikacji.
| RC KeyKlucz RC | TypeTyp | DefaultDomyślna | BehaviourDziałanie |
|---|---|---|---|
session_recording_enabled |
Boolean | true |
If false → recording is completely disabled (no sessions recorded,
regardless of enabled in code config).
If true (default) → uses whatever is set in code.
Gdy false → nagrywanie jest całkowicie wyłączone (żadna sesja nie jest nagrywana,
niezależnie od enabled w konfiguracji kodu).
Gdy true (domyślnie) → używa wartości ustawionej w kodzie.
|
session_recording_sampling_rate |
Double | -1.0 |
If >= 0.0 → overrides samplingRate from code for this session
(0.0–1.0 range is enforced automatically).
If -1.0 (default) → uses samplingRate set in code.
Gdy >= 0.0 → nadpisuje samplingRate z kodu dla tej sesji
(zakres 0.0–1.0 jest wymuszany automatycznie).
Gdy -1.0 (domyślnie) → używa samplingRate ustawionego w kodzie.
|
remote_config_defaults.xml
(session_recording_enabled = true, session_recording_sampling_rate = -1.0),
so they have no effect until you explicitly change them in the Firebase console.
Oba klucze są wstępnie skonfigurowane w remote_config_defaults.xml
(session_recording_enabled = true, session_recording_sampling_rate = -1.0),
więc nie mają żadnego efektu, dopóki nie zmienisz ich w konsoli Firebase.
Custom RC key namesWłasne nazwy kluczy RC
You can change the RC key names in SessionRecordingConfig if your project uses different naming conventions:
Możesz zmienić nazwy kluczy RC w SessionRecordingConfig, jeśli Twój projekt używa innej konwencji nazewnictwa:
ADict.SessionRecording.configure(
SessionRecordingConfig(
samplingRate = 0.2f, // 20% — kod domyślny / code default
rcKeyEnabled = "my_app_session_rec_on", // custom key name
rcKeySamplingRate = "my_app_session_rec_rate" // custom key name
)
)
Example use casesPrzykładowe scenariusze
// Wyłącz nagrywanie zdalnie (Firebase console):
// session_recording_enabled = false
// → wszystkie sesje pomijane natychmiast, bez update'u aplikacji
// Zmniejsz próbkowanie w produkcji (Firebase console):
// session_recording_sampling_rate = 0.05
// → 5% sesji nagrywanych; kod może mieć ustawione 1.0 (100%)
// Wartość -1.0 w RC = brak nadpisania (użyj wartości z kodu):
// session_recording_sampling_rate = -1.0 ← domyślna wartość w XML
Privacy & Data MaskingPrywatność i maskowanie danych
Session Recording is designed with privacy in mind: Session Recording zostało zaprojektowane z myślą o prywatności:
- Text input is always masked — characters are replaced with
•Input tekstowy jest zawsze maskowany — znaki zastępowane są znakiem• - View hierarchy snapshots never capture text content — only layout metadataSnapshoty hierarchii widoków nigdy nie przechwytują treści tekstowej — tylko metadane layoutu
- You can exclude specific Activities (e.g., login, payment screens)Możesz wykluczyć konkretne Activity (np. ekrany logowania, płatności)
- You can exclude specific view IDs (e.g., password fields)Możesz wykluczyć konkretne ID widoków (np. pola hasła)
- Screenshots (when enabled) capture actual screen content — always exclude sensitive screens via
excludedActivitiesScreenshoty (gdy włączone) przechwytują rzeczywistą zawartość ekranu — zawsze wyklucz wrażliwe ekrany przezexcludedActivities - Screenshots use low quality + downscaling to minimize readable text but still show UI flowScreenshoty używają niskiej jakości + zmniejszonej rozdzielczości aby zminimalizować czytelny tekst, ale nadal pokazywać przepływ UI
- Analytics event params can be selectively masked via
redactedAnalyticsParamKeys— e.g.,"email","user_id"Parametry eventów analitycznych mogą być selektywnie maskowane przezredactedAnalyticsParamKeys— np."email","user_id" - Analytics params length is capped by
maxAnalyticsParamsLength(default 500 chars) to prevent oversized eventsDługość parametrów analytics jest ograniczona przezmaxAnalyticsParamsLength(domyślnie 500 znaków) aby zapobiec nadmiernie dużym eventom
ADict.SessionRecording.configure(
SessionRecordingConfig(
maskAllTextInputs = true,
excludedActivities = setOf(
"LoginActivity",
"PaymentActivity",
"SettingsActivity"
),
excludedViewIds = setOf(
R.id.password_field,
R.id.credit_card_input,
R.id.ssn_field
),
// Mask sensitive analytics params
captureAnalyticsEvents = true,
redactedAnalyticsParamKeys = setOf(
"email", "user_id", "phone", "address"
),
maxAnalyticsParamsLength = 500
)
)
📸 Screenshot Presets
Instead of manually tuning screenshotMaxWidth, screenshotQuality,
and screenshotIntervalMs, use the ready-made ScreenshotPreset enum:
Zamiast ręcznie dobierać screenshotMaxWidth, screenshotQuality
i screenshotIntervalMs, użyj gotowego enuma ScreenshotPreset:
val preset = ScreenshotPreset.BALANCED // ⭐ recommended
ADict.SessionRecording.configure(
SessionRecordingConfig(
captureScreenshots = true,
screenshotMaxWidth = preset.maxWidth,
screenshotQuality = preset.quality,
screenshotIntervalMs = preset.intervalMs
)
)
| Preset | maxWidth | Quality | Interval | Per screenshotPer screenshot | 30-min session30-min sesja | Use caseZastosowanie |
|---|---|---|---|---|---|---|
MINIMAL |
360px | 25 | 3s | ~10–20 KB | ~3–6 MB | UX flow analysis (text unreadable)Analiza UX flow (tekst nieczytelny) |
BALANCED ⭐ |
540px | 40 | 2s | ~25–40 KB | ~7–12 MB | Recommended for most use casesRekomendowany dla większości |
DETAILED |
720px | 60 | 2s | ~50–90 KB | ~25–50 MB | UI bug investigation (text readable)Analiza bugów UI (tekst czytelny) |
LOW_FREQUENCY |
540px | 40 | 5s | ~25–40 KB | ~3–5 MB | Long sessions, low bandwidthDługie sesje, oszczędność pasma |
Why screenshotMaxWidth instead of screenshotScale?
A fixed scale of 0.5 produces vastly different output sizes depending on the device:
Dlaczego screenshotMaxWidth zamiast screenshotScale?
Stała skala 0.5 daje drastycznie różne rozmiary w zależności od urządzenia:
| DeviceUrządzenie | Screen widthSzerokość ekranu | scale=0.5 |
maxWidth=540 |
|---|---|---|---|
| Small phoneMały telefon | 720px | 360px (~15KB) | 540px (~35KB) |
| Regular phoneZwykły telefon | 1080px | 540px (~35KB) | 540px (~35KB) |
| Large phoneDuży telefon | 1440px | 720px (~70KB) | 540px (~35KB) |
| Tablet | 2560px | 1280px (~100KB) | 540px (~35KB) |
maxWidth gives consistent ~35KB across all devices.
maxWidth daje spójne ~35KB na wszystkich urządzeniach.
DiagnosticsDiagnostyka
// Get module diagnostics
val diag = ADict.SessionRecording.getDiagnostics()
// Returns: Map with initialized, status, sessionId, eventCount,
// bufferSize, backendStrategy, samplingRate, etc.
Log.d("SR", "Status: ${diag["status"]}")
Log.d("SR", "Events: ${diag["eventCount"]}")
Log.d("SR", "Backend: ${diag["backendStrategy"]}")
Integration with Other ModulesIntegracja z innymi modułami
📊 Analytics — Automatic Event CaptureAnalytics — automatyczne przechwytywanie eventów
When captureAnalyticsEvents = true (default) and the Analytics module is initialized,
Session Recording automatically registers itself as an Analytics provider.
Every Analytics.log(), Analytics.screenView(), Analytics.logPurchase(),
etc. call is captured as a SessionEvent.AnalyticsEvent and included in the session timeline.
Gdy captureAnalyticsEvents = true (domyślnie) i moduł Analytics jest zainicjalizowany,
Session Recording automatycznie rejestruje się jako provider Analytics.
Każde wywołanie Analytics.log(), Analytics.screenView(), Analytics.logPurchase()
itp. jest przechwytywane jako SessionEvent.AnalyticsEvent i dołączane do osi czasu sesji.
// No extra code needed! Just configure:
ADict.SessionRecording.configure(
SessionRecordingConfig(
captureAnalyticsEvents = true, // ← enabled by default
redactedAnalyticsParamKeys = setOf("email"), // mask sensitive params
)
)
// All analytics calls are now automatically captured in the session:
ADict.Analytics.log("purchase", mapOf("product_id" to "premium", "price" to 9.99))
ADict.Analytics.screenView("SettingsActivity")
ADict.Analytics.logAdImpression("banner", "ca-app-pub-xxx", "admob")
// ↑ All of these appear in the WordPress session replay timeline! 📊
How it works internally: When startSession() is called,
a SessionRecordingAnalyticsProvider is registered via Analytics.addProvider().
When stopSession() is called, the provider is removed. The provider only captures events
while the session status is RECORDING.
Jak to działa wewnętrznie: Gdy wywoływane jest startSession(),
SessionRecordingAnalyticsProvider jest rejestrowany przez Analytics.addProvider().
Gdy wywoływane jest stopSession(), provider jest usuwany. Provider przechwytuje eventy
tylko gdy status sesji to RECORDING.
Other Module IntegrationsIntegracje z innymi modułami
// With GDPR — auto-disable if no consent
if (ADict.GDPR.hasConsent()) {
ADict.SessionRecording.startSession()
}
// With AppState — auto-pause/resume
lifecycleScope.launch {
ADict.AppState.state.collect { state ->
when (state) {
AppState.State.FOREGROUND -> ADict.SessionRecording.resumeSession()
AppState.State.BACKGROUND -> ADict.SessionRecording.pauseSession()
}
}
}
API Reference
| MethodMetoda | DescriptionOpis |
|---|---|
install(app) | Initialize module (called by ADict.init)Inicjalizacja modułu (wywoływana przez ADict.init) |
configure(config) | Set recording configurationUstaw konfigurację nagrywania |
setBackendStrategy(strategy) | Set backend for data storageUstaw backend do przechowywania danych |
setUserId(id) | Assign user ID to sessionsPrzypisz ID użytkownika do sesji |
startSession() | Start recording (respects sampling)Rozpocznij nagrywanie (respektuje sampling) |
stopSession() | Stop recording and flush dataZatrzymaj nagrywanie i wyślij dane |
pauseSession() | Pause recordingWstrzymaj nagrywanie |
resumeSession() | Resume recording after pauseWznów nagrywanie po pauzie |
status | StateFlow<RecordingStatus> — observe recording stateobserwuj stan nagrywania |
currentSessionId | Current session ID or nullID bieżącej sesji lub null |
eventCount | Total events in current sessionŁączna liczba eventów w bieżącej sesji |
getDiagnostics() | Module diagnostics infoInformacje diagnostyczne modułu |