diff --git a/app/about/page.tsx b/app/about/page.tsx
index bd48ab5..a11ebf2 100644
--- a/app/about/page.tsx
+++ b/app/about/page.tsx
@@ -18,7 +18,7 @@ export default function AboutPage() {
We believe in privacy by design. Our analytics platform:
- - Uses no cookies or persistent identifiers
+ - Uses no cookies or cross-session identifiers; sessionStorage is used only to group events within a single visit
- Respects Do Not Track preferences
- Complies with GDPR and CCPA regulations
- Does not collect personal data
diff --git a/app/faq/page.tsx b/app/faq/page.tsx
index ce63261..06ed060 100644
--- a/app/faq/page.tsx
+++ b/app/faq/page.tsx
@@ -10,11 +10,15 @@ export default function FAQPage() {
},
{
question: "How does Ciphera Analytics track visitors?",
- answer: "We use a lightweight JavaScript snippet that sends anonymous pageview events. No cookies, no persistent identifiers, and no cross-site tracking."
+ answer: "We use a lightweight JavaScript snippet that sends anonymous pageview events. No cookies, no cross-session identifiers (we use sessionStorage only to group events within a single visit), and no cross-site tracking."
},
{
question: "What data does Ciphera Analytics collect?",
- answer: "We collect anonymous pageview data including page path, referrer, device type, browser, and country (from IP, not stored). No personal information is collected."
+ answer: "We collect anonymous pageview data including page path, referrer, device type, browser, and country (derived from IP at request time; the IP itself is not stored). No personal information is collected. If you enable optional session replay, see 'What about session replay?' below."
+ },
+ {
+ question: "What about session replay?",
+ answer: "Session replay is optional and off by default. When enabled, we use Anonymous Skeleton mode: all visible text is replaced with blocks, all form inputs are hidden, and we do not record canvas or fonts. We record layout, clicks, and scrolls to help you understand how visitors use your site. Replay metadata (device, browser, OS, country) is stored; we redact common PII-like URL parameters (e.g. email=, token=) before sending. Session replay uses no cookies and does not require a consent banner. We respect Do Not Trackāif it is set, replay does not run."
},
{
question: "How accurate is the data?",
diff --git a/app/security/page.tsx b/app/security/page.tsx
index 5bf1148..8a07979 100644
--- a/app/security/page.tsx
+++ b/app/security/page.tsx
@@ -16,7 +16,7 @@ export default function SecurityPage() {
- All data is encrypted in transit using TLS/SSL
- No personal data is collected or stored
- IP addresses are hashed immediately and not stored
- - No cookies or persistent identifiers are used
+ - No cookies or cross-session identifiers; sessionStorage is used only to group events within a single visit
- Data is processed anonymously
diff --git a/public/script.js b/public/script.js
index 618d5d5..f346bbd 100644
--- a/public/script.js
+++ b/public/script.js
@@ -382,13 +382,22 @@
}
}
+ // * Redact common PII-like URL query/fragment parameters in replay JSON before sending
+ function redactPiiInReplayJson(jsonStr) {
+ return jsonStr.replace(
+ /([?&])(email|token|session|auth|password|secret|api_key|apikey|access_token|refresh_token)=[^&"'\s]*/gi,
+ '$1$2=***'
+ );
+ }
+
// * Send chunk of events to server
async function sendReplayChunk() {
if (!replayId || replayEvents.length === 0) return;
const chunk = replayEvents.splice(0, CHUNK_SIZE);
const eventsCount = chunk.length;
- const data = JSON.stringify(chunk);
+ let data = JSON.stringify(chunk);
+ data = redactPiiInReplayJson(data);
try {
// Try to compress if available
@@ -437,7 +446,8 @@
// Send remaining events
if (replayEvents.length > 0) {
const chunk = replayEvents.splice(0);
- const data = JSON.stringify(chunk);
+ let data = JSON.stringify(chunk);
+ data = redactPiiInReplayJson(data);
navigator.sendBeacon(
apiUrl + '/api/v1/replays/' + replayId + '/chunks',
new Blob([data], { type: 'application/json' })