Skip to content

Commit b4edf94

Browse files
committed
update privacy policy
1 parent 4d5daae commit b4edf94

4 files changed

Lines changed: 78 additions & 31 deletions

File tree

docs/privacy-policy.html

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ <h1>Privacy Policy</h1>
299299
<p style="color: var(--text-muted); font-size: 0.875rem; margin-bottom: 2rem; text-align: center;">This policy applies to the Dota Keeper application and website, developed by <strong style="color: var(--text-secondary);">Volthawk Software (Pty) Ltd</strong> ("we", "us", or "our").</p>
300300

301301
<div class="highlight-box">
302-
<p><strong>TL;DR:</strong> The Dota Keeper <em>app</em> stores all your data locally — nothing leaves your device. This <em>website</em> uses Google Analytics to collect anonymous visitor statistics (pages visited, country, browser). We do not sell or share your personal information.</p>
302+
<p><strong>TL;DR:</strong> The Dota Keeper <em>app</em> stores all your data locally — nothing leaves your device. If you opt in to analytics, the app sends anonymous crash reports (Sentry) and usage events (PostHog) to help us improve it. This <em>website</em> uses Google Analytics to collect anonymous visitor statistics. We do not sell or share your personal information.</p>
303303
</div>
304304

305305
<!-- Table of Contents -->
@@ -357,9 +357,19 @@ <h2>1. Information We Collect</h2>
357357
<td><span class="tag tag-external">Google — anonymised</span></td>
358358
</tr>
359359
<tr>
360-
<td>App analytics, crash reports, or telemetry</td>
361-
<td>N/A</td>
362-
<td><span class="tag tag-none">Not collected</span></td>
360+
<td>Anonymous crash reports &amp; error logs</td>
361+
<td>Sentry (opt-in, app only)</td>
362+
<td><span class="tag tag-external">Sentry — anonymised</span></td>
363+
</tr>
364+
<tr>
365+
<td>Anonymous usage events (feature usage, page views)</td>
366+
<td>PostHog (opt-in, app only)</td>
367+
<td><span class="tag tag-external">PostHog — anonymised</span></td>
368+
</tr>
369+
<tr>
370+
<td>Feedback you choose to submit (text, category, app version, OS)</td>
371+
<td>Supabase (user-initiated, app only)</td>
372+
<td><span class="tag tag-external">Supabase — stored by us</span></td>
363373
</tr>
364374
<tr>
365375
<td>Advertising identifiers</td>
@@ -424,8 +434,26 @@ <h3>Google Analytics</h3>
424434
<li>Google Privacy Policy: <a href="https://policies.google.com/privacy" target="_blank" rel="noopener noreferrer">policies.google.com/privacy</a></li>
425435
</ul>
426436

437+
<h3>Sentry (App — opt-in)</h3>
438+
<p>If you opt in to analytics, the app sends anonymous crash reports and error logs to Sentry (<a href="https://sentry.io" target="_blank" rel="noopener noreferrer">sentry.io</a>). This helps us identify and fix bugs. Reports contain technical details about the error and your device environment (OS version, app version). No Steam IDs, match data, or personal information is included — Steam IDs are automatically stripped before any event is sent. You can opt out at any time in Settings.</p>
439+
<ul>
440+
<li>Sentry Privacy Policy: <a href="https://sentry.io/privacy/" target="_blank" rel="noopener noreferrer">sentry.io/privacy</a></li>
441+
</ul>
442+
443+
<h3>PostHog (App — opt-in)</h3>
444+
<p>If you opt in to analytics, the app sends anonymous usage events to PostHog (<a href="https://posthog.com" target="_blank" rel="noopener noreferrer">posthog.com</a>), such as which features are used and how often. This helps us understand how the app is being used so we can prioritise improvements. No personal data or Steam IDs are attached to these events. You can opt out at any time in Settings.</p>
445+
<ul>
446+
<li>PostHog Privacy Policy: <a href="https://posthog.com/privacy" target="_blank" rel="noopener noreferrer">posthog.com/privacy</a></li>
447+
</ul>
448+
449+
<h3>Supabase (App — feedback only)</h3>
450+
<p>When you choose to submit feedback via the in-app feedback form, your message is stored in a Supabase (<a href="https://supabase.com" target="_blank" rel="noopener noreferrer">supabase.com</a>) database that we control. The data stored is limited to: the feedback text you write, the category you select (bug/feature/positive), priority (if provided), the current page in the app, your app version, and your OS platform (e.g. "windows"). No Steam ID, username, or any other personal information is collected. Feedback submission is always voluntary and user-initiated.</p>
451+
<ul>
452+
<li>Supabase Privacy Policy: <a href="https://supabase.com/privacy" target="_blank" rel="noopener noreferrer">supabase.com/privacy</a></li>
453+
</ul>
454+
427455
<div class="highlight-box">
428-
<p><strong>No other third-party services are used in the Dota Keeper app.</strong> There are no advertising networks, social media SDKs, or tracking pixels in the app itself.</p>
456+
<p><strong>Sentry and PostHog are strictly opt-in.</strong> No telemetry data is sent until you explicitly enable analytics in the app's Settings page. Feedback via Supabase is only sent when you actively choose to submit the feedback form. There are no advertising networks, social media SDKs, or tracking pixels in the app.</p>
429457
</div>
430458
</div>
431459

@@ -473,7 +501,7 @@ <h2>8. Contact</h2>
473501
</ul>
474502
</div>
475503

476-
<p class="last-updated">Last updated: March 2026 — added Google Analytics disclosure</p>
504+
<p class="last-updated">Last updated: March 2026 — added Sentry and PostHog disclosures</p>
477505
</div>
478506
</div>
479507
</section>

src/lib/sentry.js

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,45 @@
99
import * as Sentry from '@sentry/browser';
1010

1111
let initialised = false;
12+
let sendingEnabled = false;
1213

1314
export function initSentry() {
1415
const dsn = import.meta.env.PUBLIC_SENTRY_DSN;
1516
if (!dsn) return;
1617

17-
Sentry.init({
18-
dsn,
19-
release: `dota-keeper@${__APP_VERSION__}`,
20-
environment: import.meta.env.DEV ? 'development' : 'production',
21-
// Don't send errors in dev unless DSN is explicitly set
22-
enabled: !import.meta.env.DEV || !!dsn,
23-
integrations: [
24-
Sentry.browserTracingIntegration(),
25-
],
26-
// Capture 10% of sessions for performance monitoring
27-
tracesSampleRate: 0.1,
28-
// Don't attach PII
29-
sendDefaultPii: false,
30-
beforeSend(event) {
31-
// Strip any URL that looks like it contains a Steam ID
32-
if (event.request?.url) {
33-
event.request.url = event.request.url.replace(/\d{17}/g, '[steamid]');
34-
}
35-
return event;
36-
},
37-
});
18+
if (!initialised) {
19+
Sentry.init({
20+
dsn,
21+
release: `dota-keeper@${__APP_VERSION__}`,
22+
environment: import.meta.env.DEV ? 'development' : 'production',
23+
// Don't send errors in dev unless DSN is explicitly set
24+
enabled: !import.meta.env.DEV || !!dsn,
25+
integrations: [
26+
Sentry.browserTracingIntegration(),
27+
],
28+
// Capture 10% of sessions for performance monitoring
29+
tracesSampleRate: 0.1,
30+
// Don't attach PII
31+
sendDefaultPii: false,
32+
beforeSend(event) {
33+
// Respect user's analytics consent — drop event if opted out
34+
if (!sendingEnabled) return null;
35+
// Strip any URL that looks like it contains a Steam ID
36+
if (event.request?.url) {
37+
event.request.url = event.request.url.replace(/\d{17}/g, '[steamid]');
38+
}
39+
return event;
40+
},
41+
});
42+
initialised = true;
43+
}
44+
45+
sendingEnabled = true;
46+
}
3847

39-
initialised = true;
48+
/** Stop sending events to Sentry (user opted out of telemetry). */
49+
export function disableSentry() {
50+
sendingEnabled = false;
4051
}
4152

4253
/**

src/routes/+layout.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@
4343
checkMobile();
4444
window.addEventListener('resize', checkMobile);
4545
46-
// Initialise Sentry as early as possible so it catches startup errors too
47-
initSentry();
48-
4946
await loadSettings();
5047
await checkForUpdates();
5148
@@ -70,6 +67,9 @@
7067
isLoggedIn = true;
7168
currentSteamId = settings.steam_id;
7269
}
70+
if (settings.analytics_consent === "Accepted") {
71+
initSentry();
72+
}
7373
} catch (e) {
7474
error = `Failed to load settings: ${e}`;
7575
} finally {

src/routes/settings/+page.svelte

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { onMount, onDestroy } from "svelte";
77
import { listen } from "@tauri-apps/api/event";
88
import { trackPageView, updateAnalyticsConsent } from "$lib/analytics.js";
9+
import { initSentry, disableSentry } from "$lib/sentry.js";
910
import { _ } from "svelte-i18n";
1011
1112
let databasePath = $state("");
@@ -243,6 +244,13 @@
243244
// Update the analytics module's cached state
244245
updateAnalyticsConsent(consent);
245246
247+
// Keep Sentry in sync with analytics consent
248+
if (consent === "Accepted") {
249+
initSentry();
250+
} else {
251+
disableSentry();
252+
}
253+
246254
if (consent === "Accepted") {
247255
successMessage = "Analytics enabled. Thank you for helping improve Dota Keeper!";
248256
} else if (consent === "Declined") {

0 commit comments

Comments
 (0)