update session replay tracking code UI/UX

This commit is contained in:
Francis Cao
2026-03-23 14:44:31 -07:00
parent b1e6c8f9ca
commit 85f57e90c5
5 changed files with 24 additions and 19 deletions
+1
View File
@@ -255,6 +255,7 @@
"play": "Play",
"replay": "Replay",
"replay-id": "Replay ID",
"replay-code": "Session replay code",
"replay-enabled": "Replay enabled",
"replays": "Replays",
"reports": "Reports",
@@ -7,6 +7,7 @@ import {
Select,
Slider,
Switch,
Text,
TextField,
} from '@umami/react-zen';
import { useState } from 'react';
@@ -14,6 +15,8 @@ import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
import { useMessages, useSubscription, useUpdateQuery, useWebsite } from '@/components/hooks';
import { Video } from '@/components/icons';
const RECORDER_NAME = 'recorder.js';
interface ReplayConfig {
sampleRate?: number;
maskLevel?: string;
@@ -35,6 +38,14 @@ export function WebsiteReplaySettings({ websiteId }: { websiteId: string }) {
const [maxDuration, setMaxDuration] = useState(String(config.maxDuration ?? 300000));
const [blockSelector, setBlockSelector] = useState(config.blockSelector ?? '');
const recorderUrl = cloudMode
? `${process.env.cloudUrl}/${RECORDER_NAME}`
: `${window?.location?.origin || ''}${process.env.basePath || ''}/${RECORDER_NAME}`;
let recorderAttrs = `data-website-id="${websiteId}" data-sample-rate="${sampleRate}" data-mask-level="${maskLevel}" data-max-duration="${parseInt(maxDuration, 10) || 300000}"`;
if (blockSelector) recorderAttrs += ` data-block-selector="${blockSelector}"`;
const recorderCode = `<script defer src="${recorderUrl}" ${recorderAttrs}></script>`;
const handleToggle = async (value: boolean) => {
const previous = enabled;
setEnabled(value);
@@ -106,6 +117,9 @@ export function WebsiteReplaySettings({ websiteId }: { websiteId: string }) {
</Switch>
{enabled && (
<>
<Label>{t(labels.replayCode)}</Label>
<Text color="muted">{t(messages.trackingCode)}</Text>
<TextField value={recorderCode} isReadOnly allowCopy asTextArea resize="none" className="code-textarea" />
<Slider
label={t(labels.sampleRate)}
minValue={0.05}
@@ -1,8 +1,7 @@
import { Column, Label, Text, TextField } from '@umami/react-zen';
import { useConfig, useMessages, useWebsite } from '@/components/hooks';
import { useConfig, useMessages } from '@/components/hooks';
const SCRIPT_NAME = 'script.js';
const RECORDER_NAME = 'recorder.js';
export function WebsiteTrackingCode({
websiteId,
@@ -13,7 +12,6 @@ export function WebsiteTrackingCode({
}) {
const { t, messages, labels } = useMessages();
const config = useConfig();
const website = useWebsite();
const trackerScriptName =
config?.trackerScriptName?.split(',')?.map((n: string) => n.trim())?.[0] || SCRIPT_NAME;
@@ -30,27 +28,13 @@ export function WebsiteTrackingCode({
const url = trackerScriptName?.startsWith('http') ? trackerScriptName : getUrl(trackerScriptName);
let code = `<script defer src="${url}" data-website-id="${websiteId}"></script>`;
if (website?.replayEnabled) {
const recorderUrl = getUrl(RECORDER_NAME);
const replayConfig = (website.replayConfig as any) || {};
let recorderAttrs = `data-website-id="${websiteId}"`;
if (replayConfig.sampleRate !== undefined)
recorderAttrs += ` data-sample-rate="${replayConfig.sampleRate}"`;
if (replayConfig.maskLevel) recorderAttrs += ` data-mask-level="${replayConfig.maskLevel}"`;
if (replayConfig.maxDuration !== undefined)
recorderAttrs += ` data-max-duration="${replayConfig.maxDuration}"`;
if (replayConfig.blockSelector)
recorderAttrs += ` data-block-selector="${replayConfig.blockSelector}"`;
code += `\n<script defer src="${recorderUrl}" ${recorderAttrs}></script>`;
}
const code = `<script defer src="${url}" data-website-id="${websiteId}"></script>`;
return (
<Column gap>
<Label>{t(labels.trackingCode)}</Label>
<Text color="muted">{t(messages.trackingCode)}</Text>
<TextField value={code} isReadOnly allowCopy asTextArea resize="none" />
<TextField value={code} isReadOnly allowCopy asTextArea resize="none" className="code-textarea" />
</Column>
);
}
+5
View File
@@ -56,6 +56,11 @@ select:-webkit-autofill:focus {
transition: color 5000s ease-in-out 0s;
}
/* Code snippet textareas */
.code-textarea textarea {
min-height: 100px;
}
/* rrweb-player overrides */
.rr-controller__btns {
gap: 8px;
+1
View File
@@ -371,6 +371,7 @@ export const labels: Record<string, string> = {
replay: 'label.replay',
replayId: 'label.replay-id',
replayEnabled: 'label.replay-enabled',
replayCode: 'label.replay-code',
sampleRate: 'label.sample-rate',
maskLevel: 'label.mask-level',
maxDuration: 'label.max-duration',