Skip to content

Commit d81fd84

Browse files
committed
requested changes
1 parent 1f793f5 commit d81fd84

1 file changed

Lines changed: 37 additions & 34 deletions

File tree

README.md

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -457,73 +457,76 @@ Detour.addEventListener("url", (event: DetourUrlEvent) => void): DetourUrlSubscr
457457

458458
## Privacy
459459

460-
Detour is a JavaScript-only package, so it ships no `PrivacyInfo.xcprivacy` of its own — there is no native binary to attach one to. The required-reason APIs your app touches because of Detour are already declared by its peer dependencies' own manifests, so Detour causes no `ITMS-91053` upload error. What no manifest covers is your **App Store Connect privacy questionnaire**: Apple requires the app developer to declare everything the app collects, including via SDKs, and the Privacy Report Xcode generates from your archive will not list Detour's data collection for you. Use the tables below as that reference.
460+
Detour ships no `PrivacyInfo.xcprivacy` of its own — it is a JavaScript-only package with no native binary, and the required-reason APIs it relies on are declared by its peer dependencies' own manifests. You still need to declare what Detour collects in your App Store Connect privacy questionnaire, because the Privacy Report Xcode generates from your archive will not list it for you.
461461

462462
<details>
463463
<summary>What Detour collects</summary>
464464

465-
| Data type | Details |
466-
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
467-
| Device ID | Random UUID generated on device, stored under `Detour_deviceId`, sent with every analytics event. |
468-
| Product Interaction | Event names from `DetourAnalytics.logEvent` / `logRetention` plus the optional `data` payload of `logEvent`, and universal-link opens (link URL, its query parameters, app version, OS version, device model). |
469-
| Other User Content | The whole clipboard string, read once on first launch, iOS only. Detour does not inspect or filter it — whatever the user last copied is sent as-is for deferred matching. Not read at all when `shouldUseClipboard: false`. |
470-
| Other Data Types | Deferred-matching fingerprint, sent once on first launch: device model, manufacturer, OS version, screen size and scale, locales, timezone, user agent. On Android, when an install referrer carrying a `click_id` is available, that ID is sent on its own instead. |
465+
| Data type | Details |
466+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
467+
| Device ID | Random UUID generated and stored on device, sent with every analytics event. |
468+
| Product Interaction | An `app_open` event on every cold start, sent automatically once `DetourProvider` is mounted, plus any event you log yourself with `DetourAnalytics.logEvent` / `logRetention` and the optional `data` payload. Universal-link opens are reported too: link URL, its query parameters, app version, OS version and device model. |
469+
| Other User Content | The clipboard string, read once on first launch, iOS only. It is sent and stored as-is — Detour does not filter it down to a URL. Set `shouldUseClipboard: false` to skip the read. |
470+
| Other Data Types | The deferred-matching fingerprint, sent once on first launch: device model, manufacturer, OS version, screen size and scale, locales, timezone and user agent. On Android an install referrer carrying a `click_id` is used instead when one is available. Also the IP address, which the backend reads from the request headers on every link click and match, and stores with the click. |
471471

472-
None of it is linked to the user's identity and none of it is used for tracking. "Once on first launch" is a flag in whichever storage you configure (`Detour_firstEntranceFlag`), so if your app clears that storage the deferred flow — and the clipboard read — runs again.
472+
Detour links none of this to a user identity and uses none of it for tracking. See the [Detour privacy policy](https://godetour.dev/privacy-policy) for retention details.
473473

474474
</details>
475475

476476
<details>
477477
<summary>Where the required-reason API declarations come from</summary>
478478

479-
Detour's peer dependencies ship their own privacy manifests, and those are what cover the native APIs reached on Detour's behalf:
479+
Detour's peer dependencies ship the privacy manifests covering the native APIs used on its behalf:
480480

481-
| Peer dependency | Manifest |
482-
| ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
483-
| `@react-native-async-storage/async-storage` | Declares `NSPrivacyAccessedAPICategoryUserDefaults` with reason `CA92.1` — this is what backs Detour's first-launch flag and device ID. |
484-
| `expo-application`, `expo-constants`, `expo-device`, `expo-localization`, `react-native-device-info` | Each declares its own accessed API categories. |
485-
| `expo-clipboard` | Ships no manifest, and needs none — `UIPasteboard` is not a required-reason API. |
481+
| Peer dependency | Declares |
482+
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
483+
| `@react-native-async-storage/async-storage` | `FileTimestamp` / `C617.1` |
484+
| `expo-application` | `FileTimestamp` / `C617.1` |
485+
| `expo-constants`, `expo-localization` | `UserDefaults` / `CA92.1` |
486+
| `expo-device` | `SystemBootTime` / `35F9.1` |
487+
| `react-native-device-info` | `SystemBootTime` / `35F9.1`, `UserDefaults` / `CA92.1`, `FileTimestamp` / `C617.1`, `DiskSpace` / `85F4.1` |
488+
| `expo-clipboard` | Nothing — `UIPasteboard` is not a required-reason API |
486489

487-
If you swap `@react-native-async-storage/async-storage` for a custom `storage` implementation, the declaration for whatever it persists with becomes yours to make.
490+
If you replace `@react-native-async-storage/async-storage` with a custom `storage` implementation, declaring whatever it persists with is up to you.
488491

489492
</details>
490493

491494
<details>
492495
<summary>Clipboard access shows a system paste alert (iOS)</summary>
493496

494-
`shouldUseClipboard` defaults to `true`. The read goes through `expo-clipboard`'s `getStringAsync()`, which calls `UIPasteboard.general.string` natively. When the copied content came from another app, iOS presents its own paste-permission modal (`"YourApp" would like to paste from "Safari"`) before your UI appears on first launch, and its default button denies. There is no way to suppress that alert while still reading the clipboard. Set `shouldUseClipboard: false` to skip the read entirely and never show it; deferred matching then runs without the clipboard signal.
497+
`shouldUseClipboard` defaults to `true`. The read calls `UIPasteboard.general.string` through `expo-clipboard`, so when the copied content came from another app, iOS shows its own paste-permission modal (`"YourApp" would like to paste from "Safari"`) on first launch, before your UI appears, and its default button denies. Set `shouldUseClipboard: false` to skip the read; deferred matching then runs without the clipboard signal.
495498

496499
</details>
497500

498501
<details>
499502
<summary>What to answer in App Store Connect</summary>
500503

501-
This applies to iOS submissions. In App Store Connect, go to your app → **App Privacy****Data Types****Edit**, and answer **Yes** to "Do you or your third-party partners collect data from this app?".
504+
Go to your app → **App Privacy****Data Types****Edit**, and answer Yes to "Do you or your third-party partners collect data from this app?".
502505

503-
**Step 1 — tick the applicable boxes.** They're listed here in the order they appear on screen, so you can work top to bottom:
506+
Step 1 — tick these boxes, listed in the order they appear on screen:
504507

505-
| Category | Tick | Applies when |
506-
| ------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------- |
507-
| **User Content** → Other User Content | Yes | Only if you leave `shouldUseClipboard` enabled (the default). Skip it if you set `shouldUseClipboard: false`. |
508-
| **Identifiers** → Device ID | Yes | Always — Detour generates and stores a random device ID for analytics. |
509-
| **Usage Data** → Product Interaction | Yes | Always — event names from `logEvent` / `logRetention`, plus universal-link opens. |
510-
| **Other Data** → Other Data Types | Yes | Always — the deferred-matching fingerprint. |
508+
| Category | Tick | Applies when |
509+
| --------------------------------- | ---- | ------------------------------------------- |
510+
| User Content → Other User Content | Yes | Unless you set `shouldUseClipboard: false`. |
511+
| Identifiers → Device ID | Yes | Always. |
512+
| Usage Data → Product Interaction | Yes | Always. |
513+
| Other Data → Other Data Types | Yes | Always. |
511514

512-
**Step 2 — fill in the section for each box you ticked.** Once you save, App Store Connect adds a dedicated section per data type further down the page. Click **Set Up Other User Content**, **Set Up Device ID**, and so on, and answer the three questions in each:
515+
Step 2 — App Store Connect adds a section per data type further down the page once you save. Answer the three questions in each:
513516

514-
| Data type | "Used for" (select all that apply) | "Linked to identity" | "Used for tracking" |
515-
| ------------------- | ---------------------------------- | -------------------- | ------------------- |
516-
| Other User Content | App Functionality | No | No |
517-
| Device ID | App Functionality, Analytics | No | No |
518-
| Product Interaction | App Functionality, Analytics | No | No |
519-
| Other Data Types | App Functionality | No | No |
517+
| Data type | Used for | Linked to identity | Used for tracking |
518+
| ------------------- | ---------------------------- | ------------------ | ----------------- |
519+
| Other User Content | App Functionality | No | No |
520+
| Device ID | App Functionality, Analytics | No | No |
521+
| Product Interaction | App Functionality, Analytics | No | No |
522+
| Other Data Types | App Functionality | No | No |
520523

521-
Detour itself is non-tracking: it sends nothing to an ad network or data broker and needs no App Tracking Transparency prompt. If your app declares `NSPrivacyTracking` or tracking domains, that is because of something other than Detour.
524+
Detour requires no App Tracking Transparency prompt.
522525

523-
Two things to double-check for your own app on top of this:
526+
Two things to check for your own app on top of this:
524527

525528
- Detour cannot see what you pass in `DetourAnalytics.logEvent(name, data)`. If you put personal data there, declare it yourself.
526-
- Universal-link query parameters are forwarded to Detour as-is. If your links carry personal data in params, that's yours to declare too.
529+
- Universal-link query parameters are forwarded as-is. If your links carry personal data in params, that is yours to declare too.
527530

528531
</details>
529532

0 commit comments

Comments
 (0)