Reading Pal — Privacy Policy

Effective date: 2026-05-23 — Last updated: 2026-07-15


1. Introduction

Reading Pal is a reading tracker and pomodoro timer app operated by Darren Lin (solo developer, Taiwan). This Policy explains what personal data we collect when you use Reading Pal on Android or iOS, why we collect it, who we share it with, and the rights you can exercise over it.

This Policy applies to the Reading Pal mobile application and the backend API that supports it. It does not apply to third-party services you may link (e.g., Google) — those are governed by their own privacy policies.


2. Data We Collect

(a) Account Data

Field Source Purpose
Email address You (at registration) or Google OAuth Account identity, login, account-recovery emails
Display name You or Google OAuth Shown in-app
Avatar URL Google OAuth (if applicable) Profile picture
Password hash (bcrypt) You (email+password registration only) Authentication — we never see or store your plaintext password
Locale + timezone Set at registration UI localisation; correct notification delivery times

(b) Authentication Tokens

(c) Reading Activity

(d) Device Data

Field Purpose
Anonymous device ID (UUID generated on-device) Ties push tokens and sessions to a device without linking to your phone's hardware identifier or IMEI
FCM push token (Firebase Cloud Messaging) Lets us deliver push notifications to your device
App version + OS version Crash diagnostics; compatibility checks

(e) Server Logs

Each request to our backend logs: - IP address (used for rate-limiting, security, and abuse detection — rotated automatically after 30 days) - HTTP method, URL path, response status code, response latency, request ID

We do not log request bodies in production.

(f) Audit Logs

We maintain an audit log for four event types only: deletion_requested, deletion_cancelled, deletion_executed, and export_requested. For each event we record: - Timestamp - Event type - Numeric user ID - IP address, device ID, and user-supplied deletion reason (if provided, capped at 2,000 characters) — these metadata fields are set to NULL at the moment of hard delete; only the event type, timestamp, and numeric user ID survive beyond that point

These records survive your account deletion and are retained indefinitely for compliance verification — to demonstrate that we honored your deletion or export request. After hard delete, the surviving records are fully de-identified: they contain only event type, timestamp, and a numeric user ID that no longer maps to any person (the account itself is gone). They hold no PII and no reading content.

(g) Crash and Error Reports (via Sentry)

When the app crashes or the backend encounters an error, we send a report to Sentry containing: - Stack trace - Your numeric user ID (not your email or display name) - App version and environment label - Request URL path (query strings stripped)

We explicitly do not send: your email address, display name, IP address, request body, cookies, refresh tokens, or any free-text note content.

Sentry retains these reports for 7 days (free tier default). Sentry data is hosted in the EU region (de.sentry.io). See Section 4 for Sentry's processor details.

(h) Settings and Preferences

(i) Gamification Data

(j) Analytics Data (via Firebase Analytics / Google Analytics)

We use Firebase Analytics (a Google service) to understand aggregate usage patterns and improve the app. The events and parameters we send are limited strictly to the following:

Event / Field Parameters Purpose
screen_view screen_name, screen_class Screen navigation and drop-off funnel. Values are PII-free route literals (/library, /library/[bookId], /profile/shop, etc.); dynamic IDs are replaced with literal placeholders
sign_up, login, guest_start None Auth funnel conversion rates. No email or account data attached
add_book category (e.g., fiction) Reading funnel entry and content-type preference. Category code only — no book title, content, or ISBN
start_reading_session None Reading funnel: session started. No book ID or title
complete_reading_session duration_bucket (<15, 15-30, 30-60, 60+ minutes) Reading funnel: session completed and engagement-time distribution. Coarse bucket only — no precise duration in seconds
view_subscription, begin_purchase, purchase_success product_id (SKU constant) Monetization funnel. product_id is a static SKU string, not personal data — no purchase token, amount, or payment details
view_shop, redeem_item item_id (item constant) Shop funnel. item_id is a static constant — no quantity or balance
rewarded_offer_shown, rewarded_started, rewarded_earned None Rewarded ad funnel: impression → started → completed
Firebase built-in: engagement_time, session_start, first_open Automatic Engineering metrics automatically collected by the Firebase SDK — we do not write these manually

What we do not send to Firebase Analytics: your email address, display name, book titles, note content, reading timestamps, precise reading durations, ISBNs, purchase tokens, or any free-text content.

Firebase Analytics also automatically associates events with an App Instance ID (a Firebase-generated per-install identifier, resettable by clearing app data or reinstalling) and, on Android, the Android Advertising ID (a resettable device-level ID managed by Google). These are collected by the Firebase SDK itself; we do not attach them manually.

Firebase Analytics data is processed by Google under Google's privacy terms. See Section 4.


3. How We Use Your Data

Purpose Data used
Provide the service — sync library across devices, track sessions, compute reading statistics Sections 2(a), 2(c), 2(h), 2(i)
Authentication and account security (token rotation, session invalidation) Sections 2(a), 2(b), 2(d)
Push notifications (strictly opt-in per type — see Section 10) Section 2(d) FCM token
Crash diagnostics and service reliability Section 2(g)
Security — rate-limiting by IP and device, fraud detection on auth flows, defense against credential stuffing Sections 2(d), 2(e)
Demonstrating compliance with deletion / export requests Section 2(f)
Analytics — understanding aggregate usage patterns and improving the app Section 2(j)

Email verification (email/password registration): When you register using email and password, we send a verification email containing a 6-digit code via Resend to confirm you own the email address. Signing in with Google does not trigger this flow.

In-app advertising (Google AdMob): Reading Pal displays ads served by Google AdMob (Android only; no ads on iOS). Three ad formats are used: a banner at the bottom of the book library list, a full-screen interstitial shown after a reading session of 13 minutes or more, and a rewarded ad that users can choose to watch in exchange for in-app points.

Data shared with AdMob for ad serving, measurement, and fraud prevention: the Android Advertising ID (AAID — a resettable device-level identifier managed by Google) and contextual/technical signals (app and device metadata). The AAID is already collected by the Firebase Analytics SDK (see Section 2(j) above); AdMob reuses the same identifier for advertising purposes.

For rewarded ads, we use AdMob's server-side verification (SSV): a pseudonymous numeric user ID and a custom data string are sent to AdMob solely to verify reward eligibility. This is not used for ad targeting.

We do not share with AdMob or any advertiser: your email address, display name, account data, book library, or reading content.

EEA / UK users: Google's User Messaging Platform (UMP) consent flow runs before ads are loaded. If you decline consent or applicable law requires it, only non-personalised ads are shown (or no ads at all). Ads are not loaded before consent is obtained (fail-closed).

Opt-out: Android Settings → Privacy → Ads → Reset or delete your Advertising ID.


4. Who Has Access (Sub-processors)

Provider Role Data Shared Region
Google (OAuth) Sign in with Google Standard OpenID Connect claims (sub, email, name, picture) Global
Google Firebase Cloud Messaging (FCM) Push notification delivery FCM registration token; push notification title and body Global
Google Firebase Analytics / Google Analytics Usage analytics App interaction events and parameters listed in Section 2(j); App Instance ID; Android Advertising ID (Android, SDK-automatic) Global
Google Play App distribution and licensing Standard install metadata (no reading data) Global
Sentry (Functional Software, Inc., US; data hosted EU) Crash and error monitoring See Section 2(g) — stack trace, numeric user ID, version, path EU
Resend (Resend, Inc., US; sending region set to EU — Ireland) Transactional email delivery Email address + verification code content, only when you register with email/password EU (Ireland)
Apple / APNs iOS push delivery (only when iOS version launches — currently Android-only) FCM token equivalent (APNs device token) + push payload Global
Google AdMob In-app advertising (Android) Android Advertising ID (AAID) + contextual/technical signals; rewarded-ad SSV also sends a pseudonymous numeric user ID for reward verification (not for targeting) Global

We do not sell personal data to any third party, ever.


5. International Data Transfers

All your account, library, and reading data is stored in DigitalOcean's Frankfurt (EU) data center (region: FRA1). EU users' data does not leave EU territory.

Sentry crash reports also use Sentry's EU region (de.sentry.io).

Some sub-processors (Google, AdMob) operate globally and may move data between regions for service reliability per their own privacy terms.


6. Your Rights

You can exercise most rights directly in the app without emailing us.

Right How to exercise
Access Settings → Account → "Export my data" — produces a full JSON export immediately
Rectification Settings → Profile — edit display name and other profile fields directly
Erasure (deletion) Settings → Account → "Delete account" — starts a 30-day grace period. Log back in during those 30 days to cancel. After 30 days, all personal data is permanently deleted from our database (a de-identified audit record is retained for compliance per Section 2(f)).
Portability Same JSON export as Access
Restriction Email us (Section 12)
Object to marketing Settings → Notifications → "Marketing push" — toggle off (default: off)

EU / EEA users: you also have the right to lodge a complaint with your national supervisory authority (e.g., your country's data protection authority).

Taiwan users: rights are grounded in the Personal Information Protection Act (個人資料保護法, PIPA).

We will respond to requests within 30 days of receipt.


7. Children

Reading Pal is not directed at children under 13. We do not knowingly collect personal data from users under 13. If you believe a child has created an account, email us at tn08869679@gmail.com and we will delete the account.


8. Cookies and Tracking Identifiers

Reading Pal is a mobile app — there are no web cookies. We use these identifiers:

Identifier Type Purpose Resettable?
Device ID Anonymous UUID, generated locally on first launch Sessions, push routing — no link to hardware ID Yes — uninstalling the app generates a new one
FCM token Assigned by Firebase Push notification delivery Yes — Firebase refreshes it periodically; also cleared on logout
Firebase App Instance ID Assigned by Firebase Analytics SDK on install Associates analytics events with a single install Yes — cleared when you clear app data or reinstall
Android Advertising ID Google (collected automatically by Firebase Analytics SDK on Android; also used by AdMob for ad serving) Analytics event association; AdMob ad serving & measurement Yes — Settings → Privacy → Ads → Reset Advertising ID

9. Data Retention

Data category Retention period
Account, library, reading sessions, settings, achievements, points Active until you delete your account + 30-day grace period, then hard-deleted
Audit log (deletion/export event records — no personal reading content) De-identified record (event type + timestamp + numeric user ID that no longer maps to any person) retained indefinitely for compliance verification; IP, device ID, and user-supplied reason are NULL'd at hard delete
Server access logs (IP, request metadata) 30 days, then automatic rotation
Crash reports (Sentry) 7 days (Sentry free tier default)
Refresh token records Until the token expires or is explicitly revoked
Firebase Analytics event data Governed by Google's retention settings (default 2 months for user-level data; aggregate reports may be retained longer by Google). See Google's data retention documentation.

10. Marketing Communications

Marketing push notifications default to OFF. You opt in explicitly: Settings → Notifications → "Marketing push". You can turn off any time in the same place.

We do not send marketing emails.


11. Changes to This Policy

Material changes (new data category, new sub-processor, expanded use of existing data) are announced via an in-app banner 30 days before taking effect. The updated version is dated.

Minor edits (typo fixes, clarifications that don't affect your rights) take effect immediately without prior notice.

Pre-disclosed upcoming changes:

Material changes (new data categories, new sub-processors, or expanded use of existing data) will be announced via an in-app banner at least 30 days before taking effect.


12. Contact

For privacy questions, complaints, or requests we cannot handle in-app:

We aim to respond within 30 days.


13. Effective Date and Version History

Version Date Summary
1.0 2026-05-23 Initial release
1.1 2026-06-14 Added Section 2(j) Firebase Analytics disclosure; updated Sections 3, 4, 8, 9, 11 accordingly
1.2 2026-06-23 In-app advertising (Google AdMob) updated from planned to current; updated Sections 3, 4, 8, 11 accordingly
1.3 2026-06-23 Audit log retention clarified as de-identified and indefinite (removed unimplemented 6-month deletion promise); data export timing corrected to immediate
1.4 2026-07-15 Added Resend as sub-processor (email/password registration verification emails); disclosed email verification flow