diff --git a/README.md b/README.md index e63a366c..1f3ffd1d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Platform](https://img.shields.io/badge/platform-iOS%2017%2B%20%7C%20watchOS%2010%2B-lightgrey)](#tech-stack) [![Swift](https://img.shields.io/badge/swift-5-orange)](#tech-stack) -iso.me is a location tracking app for iOS and watchOS. It automatically records the places you visit throughout the day, tracks routes with continuous GPS logging, and **keeps every byte of your data on-device**. No accounts. No cloud sync. No third-party dependencies. No analytics. Just you, your phone, and your history. +iso.me is a location tracking app for iOS and watchOS. It automatically records the places you visit throughout the day, tracks routes with continuous GPS logging, and **stores your working location journal on-device**. No iso.me account or server-side location archive. Apple geocoding and Maps services, default-on first-party onboarding telemetry, and optional exports/webhooks have specific network behavior explained in the [privacy policy](https://isome.isolated.tech/privacy). **[🌐 isome.isolated.tech](https://isome.isolated.tech)** · **[📲 Download on the App Store](https://apps.apple.com/app/id6761960794)** · **[🛠 Contribute](CONTRIBUTING.md)** · **[💬 Discussions](https://github.com/CodyBontecou/isome/discussions)** · **[👥 Discord](https://discord.gg/jNRWSSSz4N)** · **[⭐ Star this repo](https://github.com/CodyBontecou/isome)** @@ -60,11 +60,11 @@ iOS lock screen widget via Live Activities and watchOS complications for quick t Tracking is free and unlimited — visits, continuous routes, watch app, Live Activities, widgets. No subscription, no ads, no usage caps. -The one paid feature is **export**, offered as lifetime purchases with no recurring charge: +The one paid feature is **export**, offered as lifetime purchases with no recurring charge. US prices verified in App Store Connect on October 26, 2026; other storefronts vary: -- **Individual Lifetime — $10** for one Apple ID -- **Family Lifetime — $20** with Apple Family Sharing for up to five family members -- **Family Upgrade — $10** for Individual Lifetime owners who later want Family Sharing +- **Individual Lifetime — $19.99** for one Apple ID +- **Family Lifetime — $39.99** with Apple Family Sharing for up to five family members +- **Family Upgrade — $19.99** for Individual Lifetime owners who later want Family Sharing Everyone who bought the original `com.bontecou.isome.lifetime` unlock is grandfathered into Family Lifetime automatically. The split is on purpose: tracking is the commodity, but a clean, lossless export of your full history is the part that's worth paying for once. It also keeps the privacy promise free at the door — you never have to pay to keep your data on your device. @@ -75,7 +75,7 @@ Everyone who bought the original `com.bontecou.isome.lifetime` unlock is grandfa - **Data:** SwiftData - **Minimum iOS:** 17.0 - **Minimum watchOS:** 10.0 -- **Dependencies:** None (all native Apple frameworks) +- **Dependencies:** ExportKit, ExportAutomationKit, and Notelet, alongside native Apple frameworks. ### Frameworks Used diff --git a/docs/isome-seo-plan-2026-10-26.md b/docs/isome-seo-plan-2026-10-26.md index 2bb5bab8..e9dbfffc 100644 --- a/docs/isome-seo-plan-2026-10-26.md +++ b/docs/isome-seo-plan-2026-10-26.md @@ -1,5 +1,7 @@ # iso.me SEO audit and execution plan +> **Historical implementation plan.** For the current live-site audit and next priorities, use [the refreshed SEO priorities](isome-seo-priorities-2026-10-26.md). A fresh October 26 HTTP audit confirms 27 sitemap URLs are now live. The older local-only/deployment statements and no-Google-import assumptions below are historical: current app source includes a Google importer, while public App Store availability must be verified before advertising it. Do not reuse the old page-creation backlog as outstanding work. + Prepared October 26, 2026. The original audit below describes the pre-implementation site. Implementation has now started locally; no deployment, analytics changes, or scheduled jobs have been performed. ## Implementation progress — October 26, 2026 diff --git a/docs/isome-seo-priorities-2026-10-26.md b/docs/isome-seo-priorities-2026-10-26.md new file mode 100644 index 00000000..8d3fe801 --- /dev/null +++ b/docs/isome-seo-priorities-2026-10-26.md @@ -0,0 +1,153 @@ +# iso.me SEO priorities after the first guide release + +Reviewed October 26, 2026. This supersedes the outstanding-work list in [the original plan](isome-seo-plan-2026-10-26.md). The audit below is the pre-implementation assessment. See [implementation and release results](seo-implementation-2026-10-26.md) for deployed changes, verified release facts, and the remaining gates. + +## Decision + +Build on the live English cluster. First reconcile product claims, measure the acquisition path, and strengthen the private-journal, Google comparison, and GPX pages. The first new page should walk through Google Timeline import, once the public app's support is confirmed. Country Days is the next distinct scenario candidate after its release and workflow are verified. + +Apply Vaultaire's connection between a specific problem, a useful answer, related pages, and an app download. Reproduce its search-data feedback loop before its multilingual scale. Priorities below are editorial judgments based on product fit, existing evidence, and effort; search volumes and keyword difficulty have not been measured. + +## Current website: what is actually live + +The production website is **https://isome.isolated.tech/**. iso.me is the product name. Keep the existing host and `/blog/` URLs. + +A direct HTTP audit fetched all **27 sitemap URLs** successfully. Each returned 200, one H1, a unique title, an English language declaration, and the expected self-canonical. All sitemap pages were reachable within two internal-link clicks of the homepage. No language alternatives were present. These results establish delivery and basic site structure, not Google indexation or rankings. + +| Live content | Count | +| --- | ---: | +| Homepage | 1 | +| Blog hub and articles | 1 + 7 | +| Comparison hub and Google comparison | 1 + 1 | +| Documentation hub and reference pages | 1 + 11 | +| About, contact, privacy, terms | 4 | +| Total | 27 | + +The local site checker also passes: **28 HTML pages, 873 local targets**, metadata, JSON-LD, IDs, and sitemap coverage. Its 28th page is the 404 template, excluded from the sitemap. Live audit details are in [the inventory](seo-live-inventory-2026-10-26.json). Some web-search extraction still showed the previous one-article blog; the direct live fetch establishes the current inventory. + +Strengths already implemented: task-oriented homepage links and guide hub; separate setup/history/GPX/backup/support intents; crawlable static content; contextual related links; comparison content; author/review dates; screenshots; synthetic downloadable examples; accurate free-recording versus paid-export explanations. No framework migration, duplicate `/guides/` section, or broad redesign is indicated by this audit. Core Web Vitals, live mobile rendering, backlinks, and whole-property indexation were not measured in this review. + +## Priority zero: reconcile the product before expanding claims + +### Google import changes the acquisition opportunity + +The deployed Google comparison says **“No Google Timeline importer.”** The history guide says iso.me does not import Google files. The backup guide says it does not skip duplicates. These statements describe older behavior and conflict with current source: + +- `IsoMe/Utilities/GoogleTimelineImportService.swift` handles classic Location History, legacy Semantic Timeline, and device Timeline JSON. +- `IsoMe/Utilities/TimelineImportService.swift` implements preview, selected record types, and approximate duplicate detection. +- [Existing simulator QA](qa/google-timeline-import.md) records preview, cancellation, persistence, and repeated-import checks. + +Confirm support in the publicly distributed build before changing the website to an availability promise. Apple's public US lookup returned **1.7.16**, released October 26 at 15:37 UTC; the checkout targets **1.7.17**. The importer commit itself targeted 1.7.16, so the version difference does **not** establish that import is unreleased. Check the released build/source mapping or the installed App Store build. Record the verified minimum version on the relevant pages. + +Reconcile `/compare/google-maps-timeline/`, `/blog/view-location-history-iphone/`, `/docs/export-import/`, `/blog/back-up-iphone-location-history/`, and any conflicting linked copy in one content batch. Preserve valid distinctions: an importer cannot recreate unrecorded/deleted history; raw points do not imply inferred visits; GPX import remains unsupported. Separate the older iso.me restore workflow from the new Google migration workflow. + +Also reconcile prices between the website, README, and authoritative regional purchase sheet. The website quotes US $19.99/$39.99; README quotes $10/$20, also surfaced in the sampled App Store extraction. This is a consistency issue to verify, not a basis to declare one source current from cached text. Review the privacy policy/App Store disclosure alongside the actual telemetry behavior. Keep this a factual reconciliation, not a redesign project. + +### Make the acquisition path measurable + +Use the existing [Search Console baseline](search-console-baseline-2026-10-26.md): September 27–October 24 had **5 clicks, 297 impressions, 1.7% CTR**. The original journal article had **60 impressions and zero clicks**; the homepage received all five clicks. These are historical values from a filtered property, not performance of the newly deployed cluster. Query/country/device breakdowns are partial; there is no defensible country ranking or complete branded/nonbranded split. + +First measurement tasks: + +1. Record the deployment/intervention date from the release history. Check sitemap discovery and URL Inspection for the comparison, GPX, history, and original journal pages. The old report's 17 discovered URLs is not a current count. +2. Add explicit outbound `app_store_clicked` collection with page path and CTA placement, preserving the existing analytics exclusion gate. Do not include coordinates, user text, arbitrary query strings, or location files. +3. Generate genuine page-level Apple campaign links using the account's provider token. Start with home, journal, Google comparison, and GPX rather than fragmenting a tiny audience into dozens of campaigns. +4. Report organic landing visits, outbound clicks, attributable first-time downloads, and purchases separately. Apple campaign reporting has minimum thresholds; missing reports are not measured zeros. Do not promise a deterministic click-to-purchase join. + +## Ordered page backlog + +Existing pages are improvements, not pages to recreate. Effort estimates are editorial/engineering person-days, excluding App Store review, waiting for search data, and access-dependent verification. + +| Order | Action / page | Target reader intent | Concrete deliverable | Effort | +| --- | --- | --- | --- | ---: | +| 1 | Improve Google comparison + export reference | “Google Timeline alternative iPhone”; supported imports | Release-accurate migration row, preserved Google strengths, supported-format matrix, preview/deduplication limits, tested screenshot, link to migration guide when live | 1–2 days | +| 2 | Improve existing private-journal article | “private location journal iPhone”; “location history stored locally” | One verified first-recording example, current screenshots, specific privacy boundaries, contextual CTA after the successful example | 1 day | +| 3 | Improve GPX route article | “record route iPhone GPX”; “iPhone GPS logger export GPX” | Real app recording → export → opened in a named compatible viewer, measured point/time details, screenshots of the same route, clear paid-file boundary | 1–2 days | +| 4 | Create `/blog/import-google-timeline-iphone/` | “import Google Timeline iPhone”; “move Google Timeline to another app” | Versioned export-to-import walkthrough with preview, duplicates, supported Google JSON variants, failure paths, and original archive retained | 1–2 days after availability check | +| 5 | Improve history article and backup guide | Find already-recorded history; retain/restoring iso.me records | Current Apple/Google screenshots and migration link; actual clean-destination restore check and corrected duplicate behavior | 1–2 days | +| 6 | Improve `/docs/apple-watch/` | “record GPS route Apple Watch without iPhone” | Watch-only route, reconnect/Sync Now, phone route confirmation, then export; tested device/app/OS labels | 1–2 days | +| 7 | Improve homepage and hubs incrementally | Choose the right next task | Add migration link after publication; surface verified workflow proof near download; add desktop App Store QR; group support pages separately from acquisition entry points | 0.5–1 day | +| 8 | Create `/blog/track-days-in-country-iphone/` | “track days spent in each country iPhone” | Country Days setup, recorded/manual dates, travel-day/timezone example, gaps, CSV export and clear counting rules | 1–2 days after release/workflow check | +| 9 | Improve existing Obsidian article; then verify Dawarich | Use location records in another system | Add only verified plugin/mobile/scheduling behavior; publish Dawarich integration only after actual receiver persistence test | Estimate after checks | + +Order 1 corrects misleading buying information. Order 2 has the strongest existing page-level visibility evidence. Order 3 is closest to the paid export workflow. Order 4 is the first genuinely new acquisition task. If release verification blocks migration, continue the journal/GPX/Watch improvements rather than publish unsupported instructions. + +### New page brief: Google Timeline migration + +**Title:** How to Import Google Timeline into iso.me on iPhone. **URL:** `/blog/import-google-timeline-iphone/`. **Primary action:** download/open the supported app version and preview an import. Import is free in current source; clearly separate paid re-export. + +Cover one complete task: + +1. Identify the app version and supported JSON variants. Link Google's official iPhone export instructions; distinguish current device export from legacy Takeout archives. +2. Save the original archive to Files and keep a separate unchanged copy. Unzip Takeout before selecting individual JSON files. +3. In iso.me, open Settings → Data Import → Import File. Show format, date range, invalid/unsupported counts, new records, duplicates, and selection controls. +4. Demonstrate preview cancellation and a confirmed import. Review a known date on the map/Timeline. Reopen the same synthetic fixture to show the duplicate result. +5. Explain single-file limits: 50 MiB and 250,000 visits plus points; no ZIP/folder import; raw-history points do not create visits; untimed waypoints are not invented. +6. Address unsupported archives, empty results, and approximate duplicate matching. Avoid implying a lossless replica of every Google activity or label. + +Use a clearly synthetic downloadable fixture from the existing test format. Supplement existing simulator QA with the supported public build and sanitize screenshots. Link in from comparison, history article, export reference, homepage task section, and blog hub. Link out to comparison (whether to switch), backup (keeping records), and GPX (using routes). Keep export-only Google questions in this walkthrough initially instead of creating three overlapping migration pages. + +### New page brief: country-day journal + +**Title:** How to Track Days Spent in Each Country on iPhone. **URL:** `/blog/track-days-in-country-iphone/`. **Primary action:** try the free Country Days view once verified as available. + +Current source has `CountryDaysView`, `CountryDayResolver`, `CountryStay`, and `CountryDayTests`. Verify the public version before promotion. Show Timeline → Country Days, period filters, country detail, and adding a manual stay. Demonstrate a synthetic cross-border trip: dates use location timezones; a travel date can count in both countries; repeated evidence for one date is deduplicated; unknown locations and gaps are not filled; open/unverified visits contribute only arrival dates. Show what Analyze saved locations sends through Apple geocoding and how network opt-out changes the result. Country-day CSV writing uses the export purchase. + +This is a personal travel record page. Describe its actual counting rules and avoid presenting its totals as an official immigration, tax-residency, or visa calculation. Link to the history/setup guide, privacy reference, and export reference. Add deeper calculation pages only if distinct supported tasks and query demand appear. + +### Improve existing pages without creating duplicates + +- **Journal:** preserve the URL and answer immediately. The page already has setup, privacy and backup sections; replace illustrative evidence with a checked outing instead of adding more generic introduction. Keep the free-download CTA after demonstrated value and at the end. +- **Google comparison:** owns choosing a recorder, not the entire import tutorial. Acknowledge Google's device history and encrypted backup. Use its official docs and test dates. A Google account reset or export format alone proves nothing about competing security designs. +- **GPX:** owns recording/exporting a route. Name the viewer only after opening the actual exported track. Use a public route or a sanitized isolated recording, not private home coordinates. The current synthetic XML fixture is useful, but it is not evidence of a full app workflow. +- **History:** owns finding existing records; answer Apple and Google questions before offering future recording or import. Do not redirect every problem to a purchase. +- **Backup:** owns preservation and restoration; demonstrate saved records on a clean destination and distinguish GPX map files from importable records. New duplicate handling needs a release/version note. +- **Watch:** keep the existing reference URL as the intent owner. Add evidence to it before creating a separate competing Watch article. +- **Obsidian:** the existing page owns manual Markdown handoff. README links an iso.me Maps plugin, but plugin existence alone does not verify its current compatibility or mobile/scheduled delivery. Extend this page after testing before adding `/integrations/obsidian/`. +- **Shortcuts and places:** current source includes new manual-visit actions while docs still advertise nine actions. Reconcile the existing references with the released action set. Later add one real check-in/check-out recipe if supported queries justify it. + +## Practical rollout + +| Period from kickoff | Work | Completion evidence | +| --- | --- | --- | +| Days 1–2 | Public-version and pricing reconciliation; correct relevant pages; acquire baseline/indexing snapshot; specify outbound events and Apple campaigns | Release/version ledger, consistent copy, recorded measurement contract | +| Days 3–7 | Journal and GPX proof improvements; migration walkthrough if supported | Reviewed screenshots and sample, working import/export path, internal links, page-level download tracking | +| Week 2 | Backup and Watch validation; tune homepage/hub discovery; refresh history instructions | Checked restoration/transfer results, live link checks and sitemap, original pre-release baseline preserved | +| Weeks 3–4 | Review actual queries and indexation; publish country-day guide if verified and still the best product-fit next task | Source/build availability, counting example, distinct intent, no duplicate title/topic pages | +| Days 31–60 | Improve pages earning relevant impressions; select one integration or locale experiment | Evidence-based selection, explicit hypothesis and equal-window results | + +This is a focused backlog, not a commitment to publish daily. New pages should add a distinct task and first-hand proof. Google recommends useful, original content; page count and publishing cadence do not establish quality. + +## Weekly decision rules and expansion gates + +Use Search Console at the **query + page** level. Check whether an intended URL earns relevant impressions; fix indexing or answer mismatch before multiplying articles. At the present scale, one zero-click query or one high position does not establish a winner. Compare equal scoped windows after allowing for reporting lag, and retain the pre-release baseline. + +- Relevant impressions but weak positions: improve the actual answer, supporting evidence and related links first; create a URL only for a materially different task. +- Visible relevant queries but few clicks: review title/snippet and intent. Do not conclude the title caused low CTR from a handful of impressions. +- Organic visits without outbound clicks: inspect task completion, product fit, CTA timing and free/paid clarity. +- Outbound clicks without visible installs: check campaign validity, reporting thresholds, and App Store message match before concluding the page fails. + +At day 30, success first means key pages are discoverable/indexable, workflows match the app, and acquisition can be measured. At day 60, assess relevant nonbrand exposure, clicks and attributable installs, with sample sizes stated. Set business targets after usable conversion data exists instead of promising Vaultaire's reported conversion rate. + +**Localization:** the current website is English-only. Select one language using reliable App Store demand, meaningful Search Console evidence, and available language QA. There is not enough country data in the baseline to choose Spanish, Polish, or another language on SEO evidence alone. Translate a small coherent cluster: homepage, journal, best-performing acquisition page, and relevant help/navigation. Use separate localized URLs, reciprocal `hreflang`, self-canonicals, and a language selector. Do not launch 32 languages at once. + +**Tools:** defer a browser GPX/GeoJSON viewer until file-viewing queries or support needs justify it. If built later, process files locally and make its link to the recorder useful. Generic QR/image converters are a weak fit here. + +**Integrations:** keep [Dawarich](dawarich-guide-verification-2026-10-26.md) on hold until protocol, authentication and destination persistence are tested. A successful connection response does not demonstrate stored route data. Avoid speculative best-app roundups or competing scenario pages until actual product tests and demand justify them. + +**Authority:** make the verified examples and synthetic fixtures useful enough to cite. Link the documentation from the public repository and related product documentation where helpful. Outreach or community messages are a separate action; none were sent or scheduled. No backlink count or authority score was measured. + +## Execution locations and acceptance criteria + +New articles: edit `marketing/content/` and metadata/related links in `marketing/scripts/build_seo_pages.py`. Docs: edit `marketing/scripts/build_docs.py`. Homepage, blog hub and original journal: direct HTML. Rebuild with `python3 marketing/scripts/build_site.py`; run `python3 marketing/scripts/check_site.py`. Follow [the website README](../marketing/README.md). + +For each material page change: immediate useful answer, distinct intent, current supported version, checked screenshots/steps, relevant sources, truthful free/paid boundary, contextual next steps, working App Store CTA, mobile-readable tables/images, title/description/canonical consistency, appropriate structured data, and sitemap inclusion. Check deployed status separately from build success. Preserve existing URLs and only update review dates for actual reviews/changes. + +## Sources and limits + +- Live [homepage](https://isome.isolated.tech/), [blog](https://isome.isolated.tech/blog/), [comparison](https://isome.isolated.tech/compare/google-maps-timeline/), [export reference](https://isome.isolated.tech/docs/export-import/), and [sitemap](https://isome.isolated.tech/sitemap.xml). Direct crawl, October 26, 2026; basic delivery/link audit only. +- [Public App Store listing](https://apps.apple.com/us/app/iso-me/id6761960794) and [US public lookup](https://itunes.apple.com/lookup?id=6761960794&country=us). Lookup version differs from cached search extraction; neither maps every feature to a released binary. +- Existing [Search Console baseline](search-console-baseline-2026-10-26.md), [Vaultaire analysis](vaultaire-seo-analysis-2026-10-26.md), [import QA](qa/google-timeline-import.md), and current app source. Saved QA is prior evidence; no new device test was run for this planning request. +- [Google Timeline iPhone help](https://support.google.com/maps/answer/6258979?co=GENIE.Platform%3DiOS&hl=en), [Apple campaign links](https://developer.apple.com/help/app-store-connect-analytics/acquisition/campaign-links), [Google helpful-content guidance](https://developers.google.com/search/docs/fundamentals/creating-helpful-content), [localized-page guidance](https://developers.google.com/search/docs/specialty/international/localized-versions). + +No new private Search Console report, backlink dataset, keyword-volume study, conversion dataset, or performance benchmark was collected in this review. The saved baseline is clearly historical; the live audit is current to the check date. diff --git a/docs/seo-content-inventory-2026-10-26.md b/docs/seo-content-inventory-2026-10-26.md index d513289f..b1e3ab79 100644 --- a/docs/seo-content-inventory-2026-10-26.md +++ b/docs/seo-content-inventory-2026-10-26.md @@ -1,6 +1,8 @@ # iso.me article cluster inventory -Reviewed October 26, 2026. All paths below are implemented locally. They are not evidence of production deployment or measured search demand. The Search Console baseline remains the pre-deployment baseline. +Reviewed October 26, 2026. The initial direct HTTP audit confirmed the then-existing 27 sitemap URLs live. The implementation below adds the Country Days guide, bringing the live sitemap to 28 URLs. The Search Console baseline remains the pre-deployment baseline and does not measure the new cluster's results. See [the refreshed SEO priorities](isome-seo-priorities-2026-10-26.md) for the live audit and next work. + +**Release reconciliation completed:** The verified public build is 1.7.16 (46), from source preceding the importer. Public pages now state those version-specific limits; the Google migration walkthrough remains a non-public draft. Country Days is in that public build and now has a guide. See [implementation results](seo-implementation-2026-10-26.md). The following was the earlier source-drift finding: current source adds Google Timeline JSON import, preview, and duplicate detection; the live comparison, history guide, backup guide, and export reference still describe the older behavior. Align claims with confirmed public app versions. Country Days and expanded manual-visit Shortcuts also need a release-aware content review. The rows below record the original article scopes, not proof that their product claims remain current. | Page | Reader task | Distinct scope | Evidence and remaining limits | | --- | --- | --- | --- | @@ -14,6 +16,8 @@ Reviewed October 26, 2026. All paths below are implemented locally. They are not | `/blog/iphone-location-journal-obsidian/` | Read visit records in a desktop vault | Manual Markdown handoff and generated-file boundaries | Hand-authored synthetic note rendered in Obsidian 1.14.4; mobile and scheduled delivery untested | | `/docs/apple-watch/` | Record away from iPhone and check transfer | Existing feature reference, controls and status meanings | Current source and existing replay context; no new physical Watch walk claimed | +| `/blog/track-days-in-country-iphone/` | Review country dates | Counting rules, timezones, manual stays and optional CSV | Verified released source; current simulator interface capture; synthetic counting examples | + ## Reader paths The blog hub groups tasks into **find and check history**, **record and review routes**, and **keep and use records**. Each generated article offers two task-specific next steps. The original journal remains the introductory article and links to deeper workflows in context. diff --git a/docs/seo-implementation-2026-10-26.md b/docs/seo-implementation-2026-10-26.md new file mode 100644 index 00000000..f27860a9 --- /dev/null +++ b/docs/seo-implementation-2026-10-26.md @@ -0,0 +1,70 @@ +# SEO implementation and release results + +October 26, 2026. Implements the available first release of [the prioritized plan](isome-seo-priorities-2026-10-26.md). Later product releases, physical workflow checks, and traffic observation remain separate gates; this does not claim the full 60-day plan is finished. + +## Deployed + +Production: **https://isome.isolated.tech/**. Cloudflare Pages project: `spotted`. Final deployment: `9b4b2698` ([snapshot](https://9b4b2698.spotted-8ez.pages.dev)). Prior production before this batch: `9770175a`. The site now has 28 sitemap pages plus its excluded 404 template. + +- Published [Track days spent in each country on iPhone](https://isome.isolated.tech/blog/track-days-in-country-iphone/), with counting rules, travel-day and timezone examples, manual stays, geocoding boundaries, CSV limitations, current app UI, and links to setup/backup help. +- Linked the guide from the homepage, guide hub, original journal article, and Timeline reference. Added a download CTA after the journal setup steps and clarified background-permission wording. +- Added a locally generated App Store QR image and a desktop-to-phone download path. It uses the existing official app URL. +- Added explicit public-build scope to Google comparison, history, export, and backup instructions. The published limitations were accurate for the released binary even though development source had advanced. +- Reconciled README US prices and removed blanket no-analytics/no-dependencies wording that conflicted with the actual product. The website's existing prices were confirmed, not changed in App Store Connect. +- Added gated first-party acquisition counters, strict server validation, a separate aggregate D1 table, reporting SQL, privacy disclosure, public API contract, deployment migration step, and regression checks. +- Prepared the Google import article in `marketing/content/import-google-timeline-iphone.html`, with release-preview metadata and an outside-public preview command. The normal build rejects an accidentally deployed draft file. The live migration URL intentionally returns 404. + +## Release findings + +App Store Connect confirms **1.7.16 build 46** as publicly distributed. The archive source checkout was clean at `6ae78e622c72ee051e6f14113082556c398d926a`. That revision contains Country Days and predates Google Timeline import commit `0b7d5c6`. The current checkout targets 1.7.17; it was not released as part of this website task. + +Current US lifetime prices: Individual $19.99, Family $39.99, Family Upgrade $19.99. Other storefronts vary. Machine-readable, non-secret facts are saved in [the release snapshot](seo-release-facts-2026-10-26.json). + +Country Days UI was opened in the existing test simulator. Its captured development build is 1.7.17 (47), iOS 26.5; the public guide labels that fact. It shows zero resolved country dates. The counting example is invented, not a newly recorded cross-border trip. Its WebP image is approximately 53 KB. + +## Measurement contract + +`POST /api/v1/acquisition` accepts only `page_view` or `app_store_clicked`, an exact known public page path, a fixed placement, and a coarse referrer category. It rejects cross-origin/form requests, unknown fields/pages, and bodies over 512 bytes. The browser waits for the existing analytics exclusion gate, fails closed, and honors GPC/DNT. Requests omit credentials and referrer headers. + +The `website_acquisition_daily` table stores UTC day, event, public page, placement, source category, and count. No event-level log, user ID, cookies, browser storage, location file, coordinates, free text, full referrer, or query string is stored by this collector. It shares the existing D1 database but uses a separate table and never writes onboarding records. + +Page loads and activations are not unique visitors, installs, purchases, or an organic session conversion rate. The source category is per-page referrer context; the code does not preserve the original acquisition source through internal navigation. Excluded browsers, early exits, network failures, and automated requests limit interpretation. No synthetic valid event was inserted into production to inflate counts. + +Apple campaign links are now configured after explicit owner approval. An existing +signed-in App Store Connect browser session was used to generate `seo-home`, +`seo-private-journal`, `seo-google-timeline`, and `seo-gpx`. Each returned the +genuine public developer provider token `126424970`. The approved links are +applied to all download anchors on their four respective pages, including +header/footer anchors. The homepage QR was regenerated for `seo-home` and its +URL consistency is enforced by the build. Unmeasured pages and product metadata +keep the canonical App Store URL. + +Automatic review initially blocked opening campaign generation, after which the +owner explicitly authorized creating and applying the four links. That blocker +is resolved. No credentials or session tokens were copied into the repository. +Apple still reports insufficient campaign data; generation is not evidence of +installs, and its reporting thresholds/delays still apply. + +Report with the SQL command in [the website README](../marketing/README.md). No recurring automation was created. + +## Verification + +- Build: 29 HTML pages, 950 local targets, metadata, JSON-LD, canonical URLs, IDs, and sitemap coverage pass. Consecutive builds produce identical public assets. +- Acquisition regression tests: five tests covering valid counts, invalid/private dimensions, methods/origins/body bounds, unavailable binding, GPC/DNT, exclusions/gate failures, preview suppression, and no-referrer requests pass. +- Local Pages + real local D1: one page view and two activations produce two daily rows with counts one and two. These are local test data only. +- All 28 production HTML/Markdown pairs, cache separation, API representation/method behavior, missing-page responses, and asset integrity passed the HTTP checker. +- Production guide, listener, and QR returned 200 with the verification user agent; held migration URL returned 404. The live collector returned 400 for an intentionally invalid path without storing it. Generic Python requests sometimes received edge 403s; the verifier and actual Chrome loads succeeded. +- Mobile browser: homepage, journal, and new guide fit a 390-pixel viewport with no page-level horizontal overflow or broken images. The new guide's mobile Lighthouse accessibility, best-practices, SEO, and agentic-browsing scores were 100. That audit excludes performance; no new production Core Web Vitals claim is made. +- Existing public JSON samples still pass the actual Swift importer: two visits, three points, expected values, and rejection of an incomplete visit. This is parser compatibility, not a new device restore test. +- Google Search Console's live URL test reports **URL is available to Google / Page can be indexed**, with one valid Breadcrumbs item. A subsequent request confirmed **Indexing requested / URL was added to a priority crawl queue**. Google completed its verification automatically; no CAPTCHA was solved. Indexing or ranking is not yet established. + +Screenshot of the live mobile guide is retained locally at `build/seo-evidence/country-guide-mobile.png` (ignored build output). Search performance still uses the preserved September 27–October 24 baseline; it has not been recast as results of this deployment. + +## Remaining work and publication gates + +1. Confirm a public app build containing Google import, repeat preview/import/duplicate checks against it, then promote the prepared article and update linked product claims together. Do not publish it merely because source exists. +2. Capture a real recording-to-GPX-to-viewer workflow, clean-destination restore, and physical Watch-only walk/transfer before claiming those specific workflows newly verified. Existing guides remain explicit about evidence limits. +3. Verify Obsidian plugin/mobile/scheduled delivery and Dawarich receiver persistence before extending integration promises. No receiver or user data was sent to a third party in this batch. +4. Review relevant queries/indexation and acquisition counters after reporting lag. Choose further articles or a small localization pilot from meaningful demand evidence, not today's sparse sample. + +No app binary, pricing, account permissions, or scheduled automation was changed. The external changes in this batch are the website deployments, separate aggregate table, approved Apple campaign-link generation, and Google indexing request. diff --git a/docs/seo-live-inventory-2026-10-26.json b/docs/seo-live-inventory-2026-10-26.json new file mode 100644 index 00000000..3ea2aace --- /dev/null +++ b/docs/seo-live-inventory-2026-10-26.json @@ -0,0 +1,413 @@ +{ + "review_date": "2026-10-26", + "scope": "Direct HTTP fetches of the live sitemap URLs; not a Google indexation or performance audit", + "sitemap_url": "https://isome.isolated.tech/sitemap.xml", + "page_count": 27, + "pages": [ + { + "path": "/", + "status": 200, + "final": "https://isome.isolated.tech/", + "title": "Private iPhone Location History & Route Journal \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/" + ], + "description": [ + "iso.me is a private location journal for iPhone and Apple Watch. Automatically record visits and routes on-device, with no account, no iso.me location servers, and optional export in eight formats when you need your history." + ], + "hreflang": 0 + }, + { + "path": "/about", + "status": 200, + "final": "https://isome.isolated.tech/about", + "title": "About iso.me \u2014 Private iPhone Location Journal", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/about" + ], + "description": [ + "Meet iso.me, the open source iPhone and Apple Watch location journal built by Cody Bontecou at isolated.tech." + ], + "hreflang": 0 + }, + { + "path": "/blog/", + "status": 200, + "final": "https://isome.isolated.tech/blog/", + "title": "iPhone Location History Guides \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/" + ], + "description": [ + "Practical iPhone location history guides: record a private journal, compare Google Timeline, choose export formats, and understand tracking controls." + ], + "hreflang": 0 + }, + { + "path": "/blog/back-up-iphone-location-history/", + "status": 200, + "final": "https://isome.isolated.tech/blog/back-up-iphone-location-history/", + "title": "Back Up and Restore iPhone Location History \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/back-up-iphone-location-history/" + ], + "description": [ + "Export iso.me visits and GPS points as separate JSON files, verify your copies, and restore supported records. Learn what scheduled exports do and do not keep." + ], + "hreflang": 0 + }, + { + "path": "/blog/iphone-location-journal-obsidian/", + "status": 200, + "final": "https://isome.isolated.tech/blog/iphone-location-journal-obsidian/", + "title": "Export an iPhone Location Journal to Obsidian \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/iphone-location-journal-obsidian/" + ], + "description": [ + "Export iso.me visits as Markdown, copy the note into an Obsidian desktop vault, and keep your writing separate. Includes a synthetic sample and sync limits." + ], + "hreflang": 0 + }, + { + "path": "/blog/iphone-location-tracking-battery/", + "status": 200, + "final": "https://isome.isolated.tech/blog/iphone-location-tracking-battery/", + "title": "iPhone GPS Tracking and Battery Use: iso.me Settings", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/iphone-location-tracking-battery/" + ], + "description": [ + "Check iPhone battery activity, choose iso.me distance filters and auto-stop settings, and compare route detail without assuming a guaranteed battery saving." + ], + "hreflang": 0 + }, + { + "path": "/blog/missing-location-history-iphone/", + "status": 200, + "final": "https://isome.isolated.tech/blog/missing-location-history-iphone/", + "title": "Missing Visits or GPS Points in iso.me? iPhone Checks", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/missing-location-history-iphone/" + ], + "description": [ + "Diagnose an empty iso.me day, incomplete GPS route, missing visit, pending Watch sync, or filtered export. Preserve existing records before retrying." + ], + "hreflang": 0 + }, + { + "path": "/blog/private-location-journal-iphone/", + "status": 200, + "final": "https://isome.isolated.tech/blog/private-location-journal-iphone/", + "title": "How to Keep a Private Location Journal on iPhone \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/private-location-journal-iphone/" + ], + "description": [ + "A practical guide to keeping a private iPhone location journal with on-device history, local review, open-format exports, and carefully optional webhooks." + ], + "hreflang": 0 + }, + { + "path": "/blog/record-iphone-route-gpx/", + "status": 200, + "final": "https://isome.isolated.tech/blog/record-iphone-route-gpx/", + "title": "How to Record an iPhone Route and Export GPX \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/record-iphone-route-gpx/" + ], + "description": [ + "Record a route in iso.me, preview GPS points, export GPX to Files, and check the result. Includes a synthetic sample and clear free and paid limits." + ], + "hreflang": 0 + }, + { + "path": "/blog/view-location-history-iphone/", + "status": 200, + "final": "https://isome.isolated.tech/blog/view-location-history-iphone/", + "title": "How to See Your Location History on iPhone \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/blog/view-location-history-iphone/" + ], + "description": [ + "Find your own visited places in Apple Maps, check Google Timeline, and understand missing records before starting a new iPhone location journal." + ], + "hreflang": 0 + }, + { + "path": "/compare/", + "status": 200, + "final": "https://isome.isolated.tech/compare/", + "title": "Compare iPhone Location Journals \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/compare/" + ], + "description": [ + "Compare iso.me with Google Timeline on iPhone: accounts, recording, backups, exports, and the limits of moving an existing archive." + ], + "hreflang": 0 + }, + { + "path": "/compare/google-maps-timeline/", + "status": 200, + "final": "https://isome.isolated.tech/compare/google-maps-timeline/", + "title": "Google Timeline Alternative for iPhone: iso.me Compared", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/compare/google-maps-timeline/" + ], + "description": [ + "Compare iso.me and Google Timeline for iPhone: accounts, local history, encrypted backup, GPX and CSV exports, pricing, and import limitations." + ], + "hreflang": 0 + }, + { + "path": "/contact", + "status": 200, + "final": "https://isome.isolated.tech/contact", + "title": "Contact iso.me \u2014 Support and Project Links", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/contact" + ], + "description": [ + "Contact iso.me developer Cody Bontecou for support, bug reports, and questions about the private iPhone location journal." + ], + "hreflang": 0 + }, + { + "path": "/docs/", + "status": 200, + "final": "https://isome.isolated.tech/docs/", + "title": "Documentation \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/" + ], + "description": [ + "Practical guides for every corner of iso.me: tracking, timelines, exports, automation, the Apple Watch app, and privacy." + ], + "hreflang": 0 + }, + { + "path": "/docs/apple-watch/", + "status": 200, + "final": "https://isome.isolated.tech/docs/apple-watch/", + "title": "Record Apple Watch GPS routes without your iPhone \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/apple-watch/" + ], + "description": [ + "Independent watch tracking, offline sync, and complications." + ], + "hreflang": 0 + }, + { + "path": "/docs/automatic-exports/", + "status": 200, + "final": "https://isome.isolated.tech/docs/automatic-exports/", + "title": "Automatic exports \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/automatic-exports/" + ], + "description": [ + "Schedule exports once a day or every few hours, keeping one file per day." + ], + "hreflang": 0 + }, + { + "path": "/docs/export-import/", + "status": 200, + "final": "https://isome.isolated.tech/docs/export-import/", + "title": "Export and restore location history \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/export-import/" + ], + "description": [ + "Eight export formats, filters, filename templates, and free import for restores." + ], + "hreflang": 0 + }, + { + "path": "/docs/getting-started/", + "status": 200, + "final": "https://isome.isolated.tech/docs/getting-started/", + "title": "Getting started \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/getting-started/" + ], + "description": [ + "Install, onboarding, permissions, and your first tracking session." + ], + "hreflang": 0 + }, + { + "path": "/docs/photos/", + "status": 200, + "final": "https://isome.isolated.tech/docs/photos/", + "title": "Photos on the map \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/photos/" + ], + "description": [ + "Optionally connect your Photos library to place pictures on your map and outings." + ], + "hreflang": 0 + }, + { + "path": "/docs/places/", + "status": 200, + "final": "https://isome.isolated.tech/docs/places/", + "title": "Places, corrections & manual entries \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/places/" + ], + "description": [ + "Confirm or correct detected visits, save places, and add visits by hand." + ], + "hreflang": 0 + }, + { + "path": "/docs/privacy-data/", + "status": 200, + "final": "https://isome.isolated.tech/docs/privacy-data/", + "title": "Privacy & your data \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/privacy-data/" + ], + "description": [ + "What stays on your device, what can leave it, and how deletion works." + ], + "hreflang": 0 + }, + { + "path": "/docs/siri-shortcuts/", + "status": 200, + "final": "https://isome.isolated.tech/docs/siri-shortcuts/", + "title": "Siri & Shortcuts \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/siri-shortcuts/" + ], + "description": [ + "Nine actions for tracking, stats, renaming, and exports." + ], + "hreflang": 0 + }, + { + "path": "/docs/timeline-outings/", + "status": 200, + "final": "https://isome.isolated.tech/docs/timeline-outings/", + "title": "Timeline & outings \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/timeline-outings/" + ], + "description": [ + "The daily timeline, inferred outings, route replay, and editing or deleting sessions." + ], + "hreflang": 0 + }, + { + "path": "/docs/tracking/", + "status": 200, + "final": "https://isome.isolated.tech/docs/tracking/", + "title": "Visits, routes & battery \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/tracking/" + ], + "description": [ + "How automatic visit detection and route recording work, and the settings that control them." + ], + "hreflang": 0 + }, + { + "path": "/docs/webhooks/", + "status": 200, + "final": "https://isome.isolated.tech/docs/webhooks/", + "title": "Webhooks & self-hosting \u2014 iso.me Docs", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/docs/webhooks/" + ], + "description": [ + "Configure optional delivery and verify your receiver\u2019s payload and authentication requirements." + ], + "hreflang": 0 + }, + { + "path": "/privacy", + "status": 200, + "final": "https://isome.isolated.tech/privacy", + "title": "Privacy Policy \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/privacy" + ], + "description": [ + "iso.me privacy policy: location history is stored on-device with no account and no server-side location archive. Optional Apple services, first-party onboarding analytics, user-configured webhooks, and export-scheduling metadata are disclosed in full." + ], + "hreflang": 0 + }, + { + "path": "/terms", + "status": 200, + "final": "https://isome.isolated.tech/terms", + "title": "Terms of Service \u2014 iso.me", + "h1": 1, + "lang": "en", + "canonical": [ + "https://isome.isolated.tech/terms" + ], + "description": [ + "Terms for iso.me, a private iPhone location journal with local storage, free tracking, and optional export unlock." + ], + "hreflang": 0 + } + ] +} diff --git a/docs/seo-release-facts-2026-10-26.json b/docs/seo-release-facts-2026-10-26.json new file mode 100644 index 00000000..ba9ae1b1 --- /dev/null +++ b/docs/seo-release-facts-2026-10-26.json @@ -0,0 +1,33 @@ +{ + "checked_on": "2026-10-26", + "public_app": { + "version": "1.7.16", + "build": "46", + "state": "READY_FOR_DISTRIBUTION", + "source_commit": "6ae78e622c72ee051e6f14113082556c398d926a", + "google_timeline_import": false, + "country_days": true + }, + "us_lifetime_prices": { + "com.bontecou.isome.lifetime": { + "amount": "39.99", + "currency": "USD" + }, + "com.bontecou.isome.lifetime.family.upgrade": { + "amount": "19.99", + "currency": "USD" + }, + "com.bontecou.isome.lifetime.individual": { + "amount": "19.99", + "currency": "USD" + } + }, + "source_note": "App Store Connect release/build relationship; build-46 archive source checkout was clean at the recorded revision. Current development source is ahead of this binary.", + "apple_campaign_links": { + "/": "https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-home&mt=8", + "/blog/private-location-journal-iphone/": "https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-private-journal&mt=8", + "/compare/google-maps-timeline/": "https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-google-timeline&mt=8", + "/blog/record-iphone-route-gpx/": "https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-gpx&mt=8" + }, + "apple_campaign_source": "Generated in App Store Connect Campaigns UI with explicit owner approval; public provider token, not an authentication credential." +} diff --git a/marketing/README.md b/marketing/README.md index 05b6e725..314f17fb 100644 --- a/marketing/README.md +++ b/marketing/README.md @@ -74,7 +74,10 @@ python3 marketing/scripts/check_import_samples.py This checks record parsing and an invalid-file rejection, not persistence or a full device restore. Do not import sample data into a real journal just to -inspect the file format. Import currently adds records without deduplication. +inspect the file format. The verified public 1.7.16 build imports iso.me files +without the newer preview and duplicate checks. Current development source +includes Google import and duplicate handling; distinguish it from the +publicly distributed binary. The troubleshooting guide at `/blog/missing-location-history-iphone/` handles existing iso.me recordings; the broader history guide handles locating Apple, @@ -104,24 +107,87 @@ isolated.tech domain property filtered to iso.me. The dedicated URL-prefix property is processing; its sitemap already shows Success. Use the report's stored filters and date windows for repeatable comparisons. -The existing gated Cloudflare Web Analytics integration is retained. This -content batch adds no analytics endpoint, visitor identifier, or campaign token. - -1. After deployment, verify the new URLs in Search Console and confirm sitemap - discovery. Keep the saved pre-deployment baseline; record the deployment date. -2. Add an outbound `app_store_clicked` event to an approved analytics collector, - with page path and CTA placement. Preserve the current exclusion gate. Do not - send location records, user text, or arbitrary query strings. -3. Generate genuine App Store Connect campaign links using the account's - provider token. Suggested stable campaign labels: `seo-home`, - `seo-private-journal`, `seo-google-timeline`, and `seo-export-reference`. - Do not invent the provider token or treat ordinary UTM tags as Apple campaign - attribution. -4. Report organic visits, outbound clicks, visible campaign downloads, and - purchases separately. Account for reporting thresholds and delays. +The existing gated Cloudflare Web Analytics integration is retained. The shared +`public/assets/acquisition.js` adds coarse website counts after the same +exclusion gate allows collection. It also honors Global Privacy Control and Do +Not Track. It sends only an exact public page path, event, CTA placement, and +coarse referrer category. No cookies, browser storage, visitor IDs, raw URLs, +query strings, location records, or user text are collected by this listener. + +`POST /api/v1/acquisition` validates a maximum 512-byte same-origin JSON body +and updates `website_acquisition_daily` through the `SEO_DB` D1 binding. This +separate table shares the existing analytics database; it does not write app +onboarding records. Browser/gate failures lose events rather than delay a +navigation. The endpoint can receive synthetic or automated requests, so these +are coarse counters, not an audited attribution system. + +Run the privacy/validation tests: + +```sh +node --test marketing/scripts/acquisition.test.mjs +``` + +Initialize the local table and use the actual Pages runtime: + +```sh +wrangler d1 migrations apply iso-me-onboarding-analytics --local --config marketing/wrangler.jsonc +cd marketing +wrangler pages dev public --port 8892 +``` + +For a 28-day aggregate report: + +```sh +wrangler d1 execute iso-me-onboarding-analytics --remote --config marketing/wrangler.jsonc --file marketing/queries/acquisition.sql +``` + +Interpret `page_view` as page loads and `app_store_clicked` as activations, +not unique people, installs, or purchases. Referrer categories describe each +page's referrer: a later internal page does not retain the original search +source. Do not calculate an organic session conversion rate by joining these +rows. The UTC day is the server receipt day. The existing Search Console +baseline measures search-result clicks independently. + +Four pages now use Apple-generated campaign links: the homepage, private-journal +article, Google Timeline comparison, and GPX walkthrough. The genuine developer +provider token and stable campaign labels live in `content/acquisition.json`. +`campaign_links.py` rewrites download anchors during the build; public product +metadata and unmeasured pages keep their canonical App Store URLs. The homepage +QR encodes the same `seo-home` URL, checked against `assets/app-store-qr-url.txt`. +Regenerate the QR and its URL file when changing that configuration. + +Apple campaign reports have thresholds and delays. Keep organic visits, +outbound activations, visible campaign downloads, and purchases separate. + +After each deployment, record its date and inspect new URLs and sitemap +discovery in Search Console. Preserve the historical baseline and compare +explicit equal-length windows after allowing for reporting lag. A successful +HTTP response is not proof that Google indexed a page. See [Apple's campaign-link documentation](https://developer.apple.com/help/app-store-connect-analytics/acquisition/campaign-links) -and the [SEO execution plan](../docs/isome-seo-plan-2026-10-26.md). +and [the refreshed SEO priorities](../docs/isome-seo-priorities-2026-10-26.md). + +## Release-aware articles + +The Country Days guide is generated at +`/blog/track-days-in-country-iphone/` and linked from the homepage, guide hub, +and Timeline reference. The public 1.7.16 build 46 includes this feature. +Its screenshot is an iOS 26.5 simulator interface example, with no resolved +country history. Counting examples are invented, not a physical travel test. + +The Google Timeline migration walkthrough is prepared in `content/` and +listed in `DRAFTS` in `build_seo_pages.py`. It is intentionally absent from +`public/`, the sitemap, and acquisition links: the confirmed public build's +source predates the importer. Render it outside the deployment tree with: + +```sh +python3 marketing/scripts/preview_drafts.py +``` + +Before promoting it into `PAGES`, confirm the supporting public binary, +repeat import/duplicate checks, replace the release-preview notices, and +update the comparison, history, backup, and export references together. Current +source support alone is insufficient to claim App Store availability. ## Lighthouse diff --git a/marketing/content/acquisition.json b/marketing/content/acquisition.json new file mode 100644 index 00000000..97f1adad --- /dev/null +++ b/marketing/content/acquisition.json @@ -0,0 +1,9 @@ +{ + "providerToken": "126424970", + "campaigns": { + "/": "seo-home", + "/blog/private-location-journal-iphone/": "seo-private-journal", + "/compare/google-maps-timeline/": "seo-google-timeline", + "/blog/record-iphone-route-gpx/": "seo-gpx" + } +} diff --git a/marketing/content/back-up-iphone-location-history.html b/marketing/content/back-up-iphone-location-history.html index 1e7ac98c..b72fd469 100644 --- a/marketing/content/back-up-iphone-location-history.html +++ b/marketing/content/back-up-iphone-location-history.html @@ -79,7 +79,7 @@

3. Import the supported files on the destination

  • Check several dates on Map and Timeline. Look for both visits and route points, including the earliest and most recent records you expected.
  • Keep your originals until you have checked the result. An import cannot restore records that were excluded from the export.
  • -

    Import adds records; do not assume it merges an overlapping archive or skips duplicates. Import each intended file once and inspect the result before retrying. If a file fails, retain it and read the reported format or field error before editing it. A JSON archive from Google Timeline has a different structure and is not a supported iso.me restore file.

    +

    In App Store 1.7.16, import adds records without the newer preview and duplicate checks. Do not assume overlapping files are merged. Import each intended file once and inspect the result before retrying. If a file fails, retain it and read the reported format or field error before editing it. A JSON archive from Google Timeline has a different structure and is not a supported iso.me restore file.

    Restore Purchases is separate. It restores an eligible paid entitlement through the App Store; it does not download a copy of your location history. iso.me does not provide an account-based server archive or built-in iCloud journal sync.

    diff --git a/marketing/content/google-maps-timeline.html b/marketing/content/google-maps-timeline.html index 20494787..ebfae735 100644 --- a/marketing/content/google-maps-timeline.html +++ b/marketing/content/google-maps-timeline.html @@ -15,7 +15,7 @@

    Compare the everyday workflow

    Storage and backupLocal journal. Keep supported export files for restoration; no built-in cloud sync.Device history, with optional encrypted server backup. RecordingStart and Stop control GPS recording and visit monitoring together. Always permission allows background recording.Visits and routes collected with Timeline enabled. FilesJSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, and Overland. Paid export; free preview.Location-history JSON export. - Moving existing historyImports supported iso.me visit and point files. No Google Timeline importer.Timeline backup can transfer history to another device. + Moving existing historyApp Store 1.7.16 imports iso.me JSON, CSV, and Markdown files. No Google Timeline import in that build.Timeline backup can transfer history to another device. PaymentFree recording. US lifetime unlock: $19.99 Individual or $39.99 Family. Regional prices vary.Timeline is available within Google Maps. @@ -43,7 +43,7 @@

    When keeping Google Timeline makes sense

    Preserve your existing history first

    -

    Save Google’s exported archive separately before changing apps or devices. iso.me cannot import that archive or reconstruct earlier movement.

    +

    Save Google’s exported archive separately before changing apps or devices. App Store 1.7.16 cannot import that archive. A future importer still cannot reconstruct records missing from the file.

    For existing Apple or Google records, start with the iPhone history guide. For new iso.me routes, follow the GPX export walkthrough and check export and restore compatibility. A GPX file is useful for drawing a route elsewhere, but it cannot be imported into iso.me. Keep supported visit and point exports for records you want to restore later.

    diff --git a/marketing/content/import-google-timeline-iphone.html b/marketing/content/import-google-timeline-iphone.html new file mode 100644 index 00000000..cb15b26c --- /dev/null +++ b/marketing/content/import-google-timeline-iphone.html @@ -0,0 +1,7 @@ +

    Release preview: check availability before importing

    This walkthrough is prepared for the next supporting release. The currently verified App Store version, 1.7.16 build 46, does not contain this importer. Do not publish this draft as an available workflow until the released build includes Google Timeline import.

    In the supporting build, importing is free. Re-exporting files uses the optional lifetime purchase. Files are read locally without a Google login, upload, or place-name lookup by iso.me.

    +

    1. Export and keep your Google archive

    On iPhone, follow Google’s current Timeline export instructions and save the JSON to Files. Google menus can vary during rollouts. If you already have a legacy Takeout ZIP, unzip it first and choose individual JSON files. iso.me’s importer does not accept a ZIP or an entire folder.

    Retain an unchanged copy of the original. Importing a file does not move or delete Google history, and it cannot restore records absent from the archive.

    +

    2. Check which JSON you have

    Supported structures in the prepared importer
    ExportWhat iso.me can read
    Classic Location HistoryA locations array with coordinates and timestamps. Imports points, without inventing visits.
    Legacy Semantic TimelinetimelineObjects with supported place visits and timed activity paths.
    Device TimelinesemanticSegments or an iOS root array containing supported visits, activities, and timed paths.

    Each file is limited to 50 MiB and 250,000 visits plus points. Larger archives must be split before selection. Untimed waypoints are not given invented timestamps; unsupported and invalid entries appear in the preview counts.

    +

    3. Preview before saving

    1. Open Settings → Data Import → Import File and select one JSON file.
    2. Review the detected format, date range, new visits and points, duplicate counts, invalid records, and unsupported entries.
    3. Choose whether to include visits, points, or both. A raw-point archive cannot supply inferred visits.
    4. Cancel if the result is not what you expected. Preview cancellation writes nothing.
    5. Confirm only the selected records you want to add.

    The importer skips approximate matches within the file and against stored records. Points match at the same rounded second within 10 metres. Visit matching uses arrival, departure, and location tolerances. Review the counts; this is not a guarantee that every semantically similar record is identical.

    +

    4. Check the destination day

    Open Timeline or Map at a date represented in the archive. Check a known visit, its times, and the available route points. Retain the original while you inspect the result. Reopening the same file should show duplicates rather than offering those same records as new.

    The synthetic fixture used by the existing simulator QA contains one new visit, two new points, in-file duplicates, and an invalid record. It is not personal location history. That prior simulator check does not verify this workflow in a newly released App Store binary.

    +

    If the file is rejected or looks incomplete

    For choosing a recorder, read the Google Timeline comparison. For keeping supported iso.me records afterwards, use the backup guide.

    +

    Keep the original.
    Inspect the imported copy.

    Publish this guide only after checking the supporting public app version, screenshots, and fixture result.

    diff --git a/marketing/content/track-days-in-country-iphone.html b/marketing/content/track-days-in-country-iphone.html new file mode 100644 index 00000000..61302f3e --- /dev/null +++ b/marketing/content/track-days-in-country-iphone.html @@ -0,0 +1,52 @@ +
    +

    Count the dates you can account for

    +

    In iso.me, open Timeline → Country Days to count local dates represented by your recorded visits, route points, and manual stays. Choose this year, the last 365 days, or all time, then open a country to review its dates. Viewing the counts and adding manual stays are free. Writing the CSV file requires the optional export purchase.

    +

    This guide covers Country Days in iso.me 1.7.16. It is a personal travel journal: its rules do not determine tax residency, immigration status, or how a visa counts a day.

    + +
    + +
    +

    1. Review the dates behind each total

    +
    1. Open Timeline, then Country Days.
    2. Select a period. The default is this year; the other choices are the last 365 days and all time.
    3. Open a country and review the individual dates. A total is only useful when you understand which dates produced it.
    4. If older locations lack countries, use the analysis controls described below. If nothing was recorded for a stay, add it manually rather than expecting GPS to recreate it.
    +

    To collect new history, start recording before your trip. Start enables detailed GPS and visit monitoring together; Stop ends both. Read the first-recording guide for permissions and recording controls.

    +
    + +
    Country Days on iPhone, with period filters, country analysis, and Add stay controls
    Country Days before any country dates have been resolved. Captured in development build 1.7.17 (47), in an iOS 26.5 simulator on October 26, 2026; this is an interface example, not a recorded trip.
    + +
    +

    2. Check the counting rules

    +
    + + + + + + + +
    Presence dates, rather than a continuous travel guarantee
    SituationHow iso.me counts it
    Many points in the same country on one dateOne day for that country, rather than one day per record.
    Two countries on a travel dayThat date can count in both countries. Adding country totals may exceed the number of distinct dates.
    A record near midnightThe resolved location’s timezone determines the local date, rather than UTC or your phone’s current timezone.
    A completed visit with a verified departureIts local date range can contribute multiple dates.
    An open visit or unverified departureOnly its arrival date is counted. Route points or manual stays can account for other dates.
    Unknown country, GPS outlier, or recording gapNo invented dates or automatic continuous stay.
    Overlapping manual and recorded presenceThe date counts once per country; the source flags can show both.
    +

    A simple border-crossing example

    +

    Imagine a recorded point in Portugal on October 1 and another in Spain later that local date. Each country gets October 1. If a manual Portugal stay also includes October 1, Portugal still gets one day. If October 2 has no usable evidence or manual stay, the app does not fill it merely because you have records before and after it.

    +

    This is an invented example of the counting rules, not a captured trip. Review gaps with the missing-records checklist before changing your journal.

    +
    + +
    +

    3. Add a stay that was not recorded

    +

    Use Add stay in Country Days. Choose the country and first and last dates, add an optional note, and save. Review the affected country’s dates afterwards. You can edit or delete a manual stay when you find a mistake.

    +

    A manual stay records your account of a trip; it does not create a GPS path. Keep tickets or other original records separately if you need them. Overlapping manual stays do not multiply the same country/date.

    +
    + +
    +

    4. Identify countries in older locations

    +

    New recordings identify countries when network geocoding is enabled. Analyze saved locations checks earlier records in batches, with stop and resume controls. It can take time for a large archive.

    +

    Country identification uses Apple geocoding and follows your network-geocoding preference. A lookup sends coordinates to Apple; turning it off changes which unresolved locations can be assigned a country. Your journal remains on your device, and iso.me does not receive an archive of it. See the privacy policy for all network boundaries.

    +

    Analysis can identify a country for an existing coordinate. It cannot recover locations that were never recorded. Use a manual stay for dates you can account for independently.

    +
    + +
    +

    5. Keep a CSV copy of your country dates

    +

    Use the export control in Country Days and save the CSV to a destination you choose. The file includes country codes, local dates, and recorded/manual source information. Viewing and editing your counts are free; writing this export requires the lifetime unlock. See current pricing.

    +

    Check a known date and a travel day in the saved file. A country-date CSV is a summary, not a backup of every visit, route point, or manual stay. Keep your underlying records using the backup checklist.

    +
    + +

    Remember the country.
    Keep the dates behind the count.

    Start a free local journal and review Country Days on your iPhone.

    Download free for iPhone
    +

    Reviewed October 26, 2026 against the source used for App Store 1.7.16 build 46, including CountryDaysView, CountryDayCalculator, and CountryDayResolver. The examples are synthetic. They do not represent a new physical travel test.

    diff --git a/marketing/content/view-location-history-iphone.html b/marketing/content/view-location-history-iphone.html index bca903f5..16b9a203 100644 --- a/marketing/content/view-location-history-iphone.html +++ b/marketing/content/view-location-history-iphone.html @@ -39,7 +39,7 @@

    Open Google Maps Timeline

  • If history is missing, confirm which account and device you used. Check your backup and deletion settings before making changes.
  • Google Timeline stores history on the device and can keep an encrypted backup. To save an independent archive, Google’s iPhone instructions use Settings → Location & Privacy → Export Timeline data, then Save to Files. Settings are changing, so follow Google’s current Timeline guide if your menus differ.

    -

    Keep that archive separately. iso.me does not import Google Timeline files; the Google Timeline comparison explains the tradeoffs before you change your recording setup.

    +

    Keep that archive separately. The verified App Store 1.7.16 build does not import Google Timeline files; the Google Timeline comparison explains the tradeoffs before you change your recording setup.

    diff --git a/marketing/deploy.sh b/marketing/deploy.sh index 4d72b0c9..f31dc37a 100755 --- a/marketing/deploy.sh +++ b/marketing/deploy.sh @@ -4,8 +4,13 @@ set -eu MARKETING_ROOT=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) python3 "$MARKETING_ROOT/scripts/build_site.py" +node --test "$MARKETING_ROOT/scripts/acquisition.test.mjs" +wrangler d1 migrations apply iso-me-onboarding-analytics --remote --config "$MARKETING_ROOT/wrangler.jsonc" -wrangler pages deploy "$MARKETING_ROOT/public" --project-name spotted +( + cd "$MARKETING_ROOT" + wrangler pages deploy public --project-name spotted --branch main +) if command -v indexnow >/dev/null 2>&1; then indexnow submit-sitemap isome.isolated.tech --recent-days 7 --confirm diff --git a/marketing/migrations/0001_acquisition.sql b/marketing/migrations/0001_acquisition.sql new file mode 100644 index 00000000..65b7bc36 --- /dev/null +++ b/marketing/migrations/0001_acquisition.sql @@ -0,0 +1,10 @@ +-- Daily aggregate counters. No event log or visitor/location identifiers. +CREATE TABLE IF NOT EXISTS website_acquisition_daily ( + day TEXT NOT NULL, + event TEXT NOT NULL CHECK (event IN ('page_view', 'app_store_clicked')), + page TEXT NOT NULL, + placement TEXT NOT NULL, + source TEXT NOT NULL, + count INTEGER NOT NULL DEFAULT 0, + PRIMARY KEY (day, event, page, placement, source) +) WITHOUT ROWID; diff --git a/marketing/public/404.html b/marketing/public/404.html index 7c643222..5ec350e1 100644 --- a/marketing/public/404.html +++ b/marketing/public/404.html @@ -194,5 +194,6 @@ })(); + diff --git a/marketing/public/_markdown/blog/back-up-iphone-location-history/index.md b/marketing/public/_markdown/blog/back-up-iphone-location-history/index.md index 80838371..3ec21c65 100644 --- a/marketing/public/_markdown/blog/back-up-iphone-location-history/index.md +++ b/marketing/public/_markdown/blog/back-up-iphone-location-history/index.md @@ -28,23 +28,23 @@ Backup and restore checklist A GPX track can be useful in a map viewer without being a journal backup. iso.me’s importer accepts supported iso.me visit and point exports in JSON, CSV, or Markdown. It does not accept every file that happens to have one of those extensions. -What you are trying to keep -| Your goal | What to save | What to verify -| Restore visit records | Visits exported as iso.me JSON | Dates, coordinates, names, and the optional fields you need -| Restore the recorded path | Points exported as iso.me JSON | The whole date range and required point fields -| Open a route elsewhere | GPX, KML, or GeoJSON as appropriate for the viewer | Viewer compatibility; these formats cannot be imported into iso.me -| Keep every app preference or edit | A record of important settings alongside the exported files | Do not assume an import restores settings, photo associations, or edited outing summaries +What you are trying to keep +| Your goal | What to save | What to verify +| Restore visit records | Visits exported as iso.me JSON | Dates, coordinates, names, and the optional fields you need +| Restore the recorded path | Points exported as iso.me JSON | The whole date range and required point fields +| Open a route elsewhere | GPX, KML, or GeoJSON as appropriate for the viewer | Viewer compatibility; these formats cannot be imported into iso.me +| Keep every app preference or edit | A record of important settings alongside the exported files | Do not assume an import restores settings, photo associations, or edited outing summaries For restoration, choose Visits and Points individually. An outing summary is a different export from the visit and point records the importer expects. The [export reference](https://isome.isolated.tech/docs/export-import/) lists supported formats and fields. ## 1. Export your visits -- Open Export and select Visits. -- Select JSON. Deselect other formats if you only want this file. -- Choose the date range. For the full available visit archive, choose all history rather than Today or a recent period. -- Review time, duration, completion, and accuracy filters. A filter can omit records even when the date range is correct. -- Keep coordinates and the other fields you want to restore. Open Preview and check representative dates. -- Export to a folder you control. Note whether the settings produce one file or several dated files. +- Open Export and select Visits. +- Select JSON. Deselect other formats if you only want this file. +- Choose the date range. For the full available visit archive, choose all history rather than Today or a recent period. +- Review time, duration, completion, and accuracy filters. A filter can omit records even when the date range is correct. +- Keep coordinates and the other fields you want to restore. Open Preview and check representative dates. +- Export to a folder you control. Note whether the settings produce one file or several dated files. ### Then export your route points @@ -60,10 +60,10 @@ The Export screen illustrates the workflow. The screenshot may contain sample da Open Files and find the destination you selected. Confirm that you have a visit export and a point export, not just two copies of one type. If you chose daily splitting, retain every file needed for the period. -- Check the filenames and that the files are not empty. -- Use Preview or a text viewer to check early and recent dates from the intended archive. -- Keep an additional copy somewhere you will still be able to reach after changing phones. -- Preserve the originals while transferring or importing them. Check the destination copy before relying on it. +- Check the filenames and that the files are not empty. +- Use Preview or a text viewer to check early and recent dates from the intended archive. +- Keep an additional copy somewhere you will still be able to reach after changing phones. +- Preserve the originals while transferring or importing them. Check the destination copy before relying on it. A folder stored only on the old phone does not help if you erase that phone before transferring the files. If you choose a cloud folder or another service, that exported copy follows the destination’s storage and privacy rules. Location records can reveal detailed movements, so choose the destination deliberately. @@ -71,8 +71,8 @@ A folder stored only on the old phone does not help if you erase that phone befo These examples contain invented coordinates near zero and fixed dates on January 1, 2000. They are documentation fixtures, not a real trip or captured app exports: -- [Download the synthetic Visits JSON](https://isome.isolated.tech/samples/synthetic-visits.json): two named stops with arrival and departure times. -- [Download the synthetic Points JSON](https://isome.isolated.tech/samples/synthetic-points.json): three timestamped locations matching the [synthetic GPX example](https://isome.isolated.tech/samples/synthetic-route.gpx). +- [Download the synthetic Visits JSON](https://isome.isolated.tech/samples/synthetic-visits.json): two named stops with arrival and departure times. +- [Download the synthetic Points JSON](https://isome.isolated.tech/samples/synthetic-points.json): three timestamped locations matching the [synthetic GPX example](https://isome.isolated.tech/samples/synthetic-route.gpx). ``` { @@ -93,13 +93,13 @@ Open the samples as text to inspect them. Importing them into your everyday jour ## 3. Import the supported files on the destination -- Make the saved visit and point files available in Files on the destination iPhone. -- Open iso.me, then choose Settings → Import file. -- Select a supported iso.me file and read the import result. Repeat for the other data type and any additional dated files. -- Check several dates on Map and Timeline. Look for both visits and route points, including the earliest and most recent records you expected. -- Keep your originals until you have checked the result. An import cannot restore records that were excluded from the export. +- Make the saved visit and point files available in Files on the destination iPhone. +- Open iso.me, then choose Settings → Import file. +- Select a supported iso.me file and read the import result. Repeat for the other data type and any additional dated files. +- Check several dates on Map and Timeline. Look for both visits and route points, including the earliest and most recent records you expected. +- Keep your originals until you have checked the result. An import cannot restore records that were excluded from the export. -Import adds records; do not assume it merges an overlapping archive or skips duplicates. Import each intended file once and inspect the result before retrying. If a file fails, retain it and read the reported format or field error before editing it. A JSON archive from Google Timeline has a different structure and is not a supported iso.me restore file. +In App Store 1.7.16, import adds records without the newer preview and duplicate checks. Do not assume overlapping files are merged. Import each intended file once and inspect the result before retrying. If a file fails, retain it and read the reported format or field error before editing it. A JSON archive from Google Timeline has a different structure and is not a supported iso.me restore file. Restore Purchases is separate. It restores an eligible paid entitlement through the App Store; it does not download a copy of your location history. iso.me does not provide an account-based server archive or built-in iCloud journal sync. @@ -122,7 +122,7 @@ Check the copy. Try free recording and export preview. See [current pricing](https://isome.isolated.tech/#pricing) for the optional file-export unlock. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) Reviewed October 26, 2026 against iso.me’s export, import, and scheduling behavior. Importing restores supported records; it is not a promise to reproduce every app setting or edited view. diff --git a/marketing/public/_markdown/blog/index.md b/marketing/public/_markdown/blog/index.md index fda4a8da..b5555b35 100644 --- a/marketing/public/_markdown/blog/index.md +++ b/marketing/public/_markdown/blog/index.md @@ -1,10 +1,10 @@ -Practical guides · iso.me +Practical guides · iso.me # Keep a useful location history on iPhone. -Choose how to record your own visits and routes, keep portable files, and understand what stays on your phone. Start with a setup guide or compare the tools before changing your workflow. +Choose how to record your own visits and routes, keep portable files, and understand what stays on your phone. Start with a setup guide or compare the tools before changing your workflow. -[Set up your journal](https://isome.isolated.tech/blog/private-location-journal-iphone/) [Compare Google Timeline](https://isome.isolated.tech/compare/google-maps-timeline/) +[Set up your journal](https://isome.isolated.tech/blog/private-location-journal-iphone/) [Compare Google Timeline](https://isome.isolated.tech/compare/google-maps-timeline/) What do you need? @@ -34,28 +34,28 @@ Compare accounts, recording, backups, export formats, and migration limits. Read -Private location journal Product notes Release updates Export guides On-device history Apple Watch companion Private location journal Product notes Release updates Export guides On-device history Apple Watch companion +Private location journal Product notes Release updates Export guides On-device history Apple Watch companion Private location journal Product notes Release updates Export guides On-device history Apple Watch companion -§ 01 Record your history +§ 01 Record your history ## Make your first recorded day useful. Guide -Private location history +Private location history Published guide ## [How to Keep a Private Location Journal on iPhone](https://isome.isolated.tech/blog/private-location-journal-iphone/) -A practical walkthrough for using iso.me as a local-first place and route journal: what to record, how to review the map, when to export JSON, CSV, Markdown, GPX, KML, or GeoJSON, and how to treat optional webhooks as an explicit privacy boundary. +A practical walkthrough for using iso.me as a local-first place and route journal: what to record, how to review the map, when to export JSON, CSV, Markdown, GPX, KML, or GeoJSON, and how to treat optional webhooks as an explicit privacy boundary. -Status Published +Status Published -Topics Privacy · Export · Webhooks +Topics Privacy · Export · Webhooks -Updated October 2026 +Updated October 2026 -On-device Route history Open exports Optional automation +On-device Route history Open exports Optional automation Compare your options @@ -133,6 +133,14 @@ Keep separate visit and point files, verify what was saved, and understand what [Follow the backup checklist](https://isome.isolated.tech/blog/back-up-iphone-location-history/) +Travel journal guide + +### [Track days spent in each country](https://isome.isolated.tech/blog/track-days-in-country-iphone/) + +Check local dates, travel days, and gaps. Add a manual stay and understand the CSV export. + +[Review your country dates](https://isome.isolated.tech/blog/track-days-in-country-iphone/) + Markdown journal workflow ### [Read your location journal in Obsidian](https://isome.isolated.tech/blog/iphone-location-journal-obsidian/) @@ -141,13 +149,13 @@ Copy a Markdown visit export into a desktop vault, inspect the table, and keep p [Follow the manual Markdown workflow](https://isome.isolated.tech/blog/iphone-location-journal-obsidian/) -§ 02 Export and connect +§ 02 Export and connect ## Keep your records useful outside the app. Files Recording -Apple Watch +Apple Watch 01 diff --git a/marketing/public/_markdown/blog/iphone-location-journal-obsidian/index.md b/marketing/public/_markdown/blog/iphone-location-journal-obsidian/index.md index 31f260f4..331e3254 100644 --- a/marketing/public/_markdown/blog/iphone-location-journal-obsidian/index.md +++ b/marketing/public/_markdown/blog/iphone-location-journal-obsidian/index.md @@ -30,21 +30,21 @@ A visit export is a practical starting point when you want to remember stops rat A Points export is different: it lists recorded locations with times and optional speed, altitude, accuracy, and outlier information. A long recording can produce a large table. Markdown does not turn those rows into a route map in Obsidian. -Match the file to the task -| What you want | Choose | Check before saving -| A list of places and stops | Visits → Markdown | Date range, names, notes, and the columns you need -| Timestamped GPS rows | Points → Markdown | Point count, accuracy filters, and file size -| A route for a map viewer | Points → GPX | Use the [GPX walkthrough](https://isome.isolated.tech/blog/record-iphone-route-gpx/); this guide does not add a map plugin -| A copy for restoring supported records | Separate Visits and Points JSON files | Use the [backup checklist](https://isome.isolated.tech/blog/back-up-iphone-location-history/) alongside your readable notes +Match the file to the task +| What you want | Choose | Check before saving +| A list of places and stops | Visits → Markdown | Date range, names, notes, and the columns you need +| Timestamped GPS rows | Points → Markdown | Point count, accuracy filters, and file size +| A route for a map viewer | Points → GPX | Use the [GPX walkthrough](https://isome.isolated.tech/blog/record-iphone-route-gpx/); this guide does not add a map plugin +| A copy for restoring supported records | Separate Visits and Points JSON files | Use the [backup checklist](https://isome.isolated.tech/blog/back-up-iphone-location-history/) alongside your readable notes ## 1. Export the date range as Markdown -- In iso.me, open Export and select Visits. -- Select Markdown. Deselect other formats if you only want the note file. -- Choose the day or date range. Review duration, completion, and time filters so they do not remove visits you wanted to keep. -- Choose the visit fields. For a readable note, names and notes may matter more than coordinates. Keep a separate supported backup if you need restoration later. -- Open Preview. Check a known stop and its date before writing the file. -- Export to your chosen folder, or use the share sheet to save in Files. Confirm that the `.md` file exists. +- In iso.me, open Export and select Visits. +- Select Markdown. Deselect other formats if you only want the note file. +- Choose the day or date range. Review duration, completion, and time filters so they do not remove visits you wanted to keep. +- Choose the visit fields. For a readable note, names and notes may matter more than coordinates. Keep a separate supported backup if you need restoration later. +- Open Preview. Check a known stop and its date before writing the file. +- Export to your chosen folder, or use the share sheet to save in Files. Confirm that the `.md` file exists. For one file per day, enable the daily output layout and inspect the resolved filename preview. A template such as `{date}-visits` can make files easier to recognize. Treat it as an example; check the actual generated filename before copying it into your vault. @@ -54,11 +54,11 @@ Visit table dates and times are formatted using the device’s calendar and loca Make the saved export available on the computer where you use Obsidian. Use a transfer destination you control. This step moves location records outside iso.me’s local journal, so the destination’s storage and sharing settings apply. -- Find the folder for the Obsidian vault you intend to use. -- Create a subfolder such as `Location` for generated exports. -- Copy the Markdown file into that subfolder. Keep the original until you have checked the copy. -- In Obsidian’s file explorer, open the note. Switch to Reading view if you want to inspect the rendered table. -- Verify the date heading, number of visits, names, and times against iso.me’s Preview. +- Find the folder for the Obsidian vault you intend to use. +- Create a subfolder such as `Location` for generated exports. +- Copy the Markdown file into that subfolder. Keep the original until you have checked the copy. +- In Obsidian’s file explorer, open the note. Switch to Reading view if you want to inspect the rendered table. +- Verify the date heading, number of visits, names, and times against iso.me’s Preview. Obsidian documents both copying Markdown directly into a vault folder and dragging it into the file explorer in its [Markdown import guide](https://obsidian.md/help/import/markdown). Its [storage guide](https://obsidian.md/help/Files%2Band%2Bfolders/How%2BObsidian%2Bstores%2Bdata) explains that a vault is a folder of local files and reflects external file changes. @@ -102,7 +102,7 @@ Add your own context. Try free recording and Markdown preview. See [current pricing](https://isome.isolated.tech/#pricing) for the optional file-export unlock. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) Reviewed October 26, 2026 against iso.me’s Markdown exporter and Obsidian’s linked documentation. A synthetic note was rendered in a temporary desktop vault. Mobile handoff and scheduled vault delivery remain untested. diff --git a/marketing/public/_markdown/blog/iphone-location-tracking-battery/index.md b/marketing/public/_markdown/blog/iphone-location-tracking-battery/index.md index 4b0f0ff5..68c9e031 100644 --- a/marketing/public/_markdown/blog/iphone-location-tracking-battery/index.md +++ b/marketing/public/_markdown/blog/iphone-location-tracking-battery/index.md @@ -32,12 +32,12 @@ Note the recording duration, starting and ending charge, screen use, and whether ## 2. Change the controls that affect your recording -What each control changes in iso.me -| Control | What changes | What to check -| Stop recording | Ends the active recording and stops its GPS, visit, and significant-change monitoring. | Confirm the tracking state changed. Future movement will not be captured by that stopped session. -| Distance filter | Changes the movement threshold requested for location updates. Options are 5, 10, 25, 50, 100, and 200 meters. | Larger values can mean fewer points and less route detail. They do not switch off high-accuracy GPS. -| Stop after | Adds an automatic stopping timer: 1, 2, 4, 8, or 12 hours, or Never. | Choose enough time for the intended route, and still check the final recording state. -| Location names | Controls sending coordinates to Apple’s geocoding service to name visits. | Turning names off does not stop GPS recording or create a visits-only mode. +What each control changes in iso.me +| Control | What changes | What to check +| Stop recording | Ends the active recording and stops its GPS, visit, and significant-change monitoring. | Confirm the tracking state changed. Future movement will not be captured by that stopped session. +| Distance filter | Changes the movement threshold requested for location updates. Options are 5, 10, 25, 50, 100, and 200 meters. | Larger values can mean fewer points and less route detail. They do not switch off high-accuracy GPS. +| Stop after | Adds an automatic stopping timer: 1, 2, 4, 8, or 12 hours, or Never. | Choose enough time for the intended route, and still check the final recording state. +| Location names | Controls sending coordinates to Apple’s geocoding service to name visits. | Turning names off does not stop GPS recording or create a visits-only mode. Find these options under Settings → Location tracking. For a longer outing, you could try a 25 or 50 meter distance filter on a short, familiar route before using it for a full day. That is a starting point for comparison, not a measured battery recommendation. @@ -47,11 +47,11 @@ Use Stop after as a fallback for a forgotten session. If the timer expires durin ## 3. Compare one change on a familiar route -- Choose a short route with turns and stops you can recognize later. Note the current distance filter and intended recording duration. -- Start recording and check that the app shows an active session. Keep screen use representative of how you normally record. -- Stop at the end. In Timeline, open the outing and inspect the path, times, turns, and gaps. -- On another comparable trip, change only the distance filter. Note differences in charge use and route detail rather than assuming the setting is better because it is larger. -- Keep the setting that preserves the detail you need. Repeat if the two trips had substantially different conditions. +- Choose a short route with turns and stops you can recognize later. Note the current distance filter and intended recording duration. +- Start recording and check that the app shows an active session. Keep screen use representative of how you normally record. +- Stop at the end. In Timeline, open the outing and inspect the path, times, turns, and gaps. +- On another comparable trip, change only the distance filter. Note differences in charge use and route detail rather than assuming the setting is better because it is larger. +- Keep the setting that preserves the detail you need. Repeat if the two trips had substantially different conditions. A route with fewer points may be adequate for remembering a journey but miss a short detour you care about. An export contains the recorded points; exporting GPX cannot add detail that was never captured. Use the [GPX walkthrough](https://isome.isolated.tech/blog/record-iphone-route-gpx/) when you want to inspect a saved route in another tool. @@ -84,7 +84,7 @@ Check where it ends. Try free recording and review your first short outing before choosing settings for a longer day. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) Reviewed October 26, 2026 against iso.me’s recording controls and Apple’s linked guidance. No new device battery benchmark was performed. Controls can vary by app and iOS version. diff --git a/marketing/public/_markdown/blog/missing-location-history-iphone/index.md b/marketing/public/_markdown/blog/missing-location-history-iphone/index.md index 4e7e6c19..c8f02820 100644 --- a/marketing/public/_markdown/blog/missing-location-history-iphone/index.md +++ b/marketing/public/_markdown/blog/missing-location-history-iphone/index.md @@ -26,14 +26,14 @@ Choose the symptom ## Match the symptom before changing anything -Start with the closest match -| What you see | First check | Next step -| The whole day is empty | Timeline date and Map date range | Confirm whether recording was running during that period. -| A path ends partway through | Stop time and Stop after setting | Inspect the last recorded point and check permission. -| A route exists but a stop is missing | Route points at the expected stop | Review visit detection separately; a path is not a list of confirmed visits. -| Watch recorded, phone looks empty | Watch sync message and recording date | Open both apps, check transfer, then inspect the phone’s day. -| Timeline has data, export is empty | Export data type, dates, and filters | Check Preview before writing another file. -| A visit has coordinates but no useful name | Location names setting and place correction | Review or rename the visit instead of treating it as absent. +Start with the closest match +| What you see | First check | Next step +| The whole day is empty | Timeline date and Map date range | Confirm whether recording was running during that period. +| A path ends partway through | Stop time and Stop after setting | Inspect the last recorded point and check permission. +| A route exists but a stop is missing | Route points at the expected stop | Review visit detection separately; a path is not a list of confirmed visits. +| Watch recorded, phone looks empty | Watch sync message and recording date | Open both apps, check transfer, then inspect the phone’s day. +| Timeline has data, export is empty | Export data type, dates, and filters | Check Preview before writing another file. +| A visit has coordinates but no useful name | Location names setting and place correction | Review or rename the visit instead of treating it as absent. Note the date and approximate time of the gap. Compare Map and Timeline for that same period. A Map range excluding yesterday and a Timeline opened on today can make retained history look missing. @@ -41,10 +41,10 @@ Note the date and approximate time of the gap. Compare Map and Timeline for that Start enables GPS recording, visit monitoring, and significant location changes together. Stop ends those services. A location permission alone does not mean a recording was active. The app’s current recording state also cannot prove that it was running throughout yesterday’s trip. -- Open the expected day in Timeline and inspect any outing’s start and end times. -- Check Settings → Location tracking → Stop after. A timer shorter than the trip can explain why its later section was not recorded. -- For a new short test, tap Start and confirm the recording state changes. After a permission prompt, check the state again rather than assuming the session began. -- Finish the test with Stop, then inspect its route and times in Timeline. +- Open the expected day in Timeline and inspect any outing’s start and end times. +- Check Settings → Location tracking → Stop after. A timer shorter than the trip can explain why its later section was not recorded. +- For a new short test, tap Start and confirm the recording state changes. After a permission prompt, check the state again rather than assuming the session began. +- Finish the test with Stop, then inspect its route and times in Timeline. Review the app’s permission under iPhone Settings → Privacy & Security → Location Services. iso.me offers Always access for background visit monitoring; an active manual session and automatic visit detection have different permission needs. Follow [Apple’s Location Services instructions](https://support.apple.com/en-us/102515) if the controls on your iOS version differ. @@ -54,9 +54,9 @@ Changing permission can help a future recording. It does not fill an earlier gap A sparse route can come from the chosen distance filter, rejected GPS fixes, or points hidden as glitches. These are different from a session that never ran. -- Distance filter: a larger value requests updates after more movement. Compare the setting with a short route before relying on it for detail such as small turns. -- Rejected fixes: iso.me saves incoming route locations only when reported accuracy is between zero and 100 meters. A fix outside that range is not a hidden point you can reveal later. -- Hidden glitches: some saved points are flagged as outliers. Enable Settings → Map display → Show GPS glitches to inspect them. A newly visible spike is not evidence that you travelled along it. +- Distance filter: a larger value requests updates after more movement. Compare the setting with a short route before relying on it for detail such as small turns. +- Rejected fixes: iso.me saves incoming route locations only when reported accuracy is between zero and 100 meters. A fix outside that range is not a hidden point you can reveal later. +- Hidden glitches: some saved points are flagged as outliers. Enable Settings → Map display → Show GPS glitches to inspect them. A newly visible spike is not evidence that you travelled along it. If the route is visible in iso.me but absent from a file, choose Points in Export, select the same dates, and review accuracy and glitch filters in Preview. A Visits GPX contains stops rather than the continuous path. Follow the [GPX export walkthrough](https://isome.isolated.tech/blog/record-iphone-route-gpx/) for file checks. @@ -86,10 +86,10 @@ Import adds records without a duplicate check. Repeatedly importing an overlappi ### What to include when asking for help -- App and iOS versions, plus whether the recording came from iPhone or Watch. -- The affected date, approximate time, and timezone. -- Whether the problem is missing points, visits, names, sync, or an export. -- The recording state, Stop after value, and any exact error or sync message. +- App and iOS versions, plus whether the recording came from iPhone or Watch. +- The affected date, approximate time, and timezone. +- Whether the problem is missing points, visits, names, sync, or an export. +- The recording state, Stop after value, and any exact error or sync message. Describe the symptom before sending a route file. You can [contact support](mailto:cody.bontecou@gmail.com) without including your coordinates or a full location archive. @@ -98,7 +98,7 @@ Then trust a longer day. Recording and reviewing history are free. Check one finished session before relying on a new setup for a long trip. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) Reviewed October 26, 2026 against iso.me’s recording, filtering, import, and Watch-sync source. This is a diagnostic checklist, not a guarantee of recovering deleted or unrecorded movement. Controls can vary by version. diff --git a/marketing/public/_markdown/blog/private-location-journal-iphone/index.md b/marketing/public/_markdown/blog/private-location-journal-iphone/index.md index f91668bb..6b163dde 100644 --- a/marketing/public/_markdown/blog/private-location-journal-iphone/index.md +++ b/marketing/public/_markdown/blog/private-location-journal-iphone/index.md @@ -1,10 +1,10 @@ -Guide · Reviewed October 26, 2026 +Guide · Reviewed October 26, 2026 # How to keep a private location journal on iPhone. -To keep a private location journal on iPhone, enable recording in iso.me, check a short route in Timeline, and keep supported exports for records you want to restore later. Your visits and routes stay on your phone unless you export or configure delivery elsewhere. +To keep a private location journal on iPhone, enable recording in iso.me, check a short route in Timeline, and keep supported exports for records you want to restore later. Your visits and routes stay on your phone unless you export or configure delivery elsewhere. -[Start the checklist](https://isome.isolated.tech/blog/private-location-journal-iphone/#setup) [Get iso.me](https://apps.apple.com/us/app/iso-me/id6761960794) +[Start the checklist](https://isome.isolated.tech/blog/private-location-journal-iphone/#setup) [Get iso.me](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-private-journal&mt=8) Private journal setup @@ -28,125 +28,129 @@ Use files like JSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, or Overland wh Webhooks can be useful, but only point them at endpoints you trust. -Published June 13, 2026 +Published June 13, 2026 -Reading time 7 minutes +Reading time 7 minutes -Topic Private location history +Topic Private location history -App iso.me for iPhone +App iso.me for iPhone ## In this guide -- [Why keep it private?](https://isome.isolated.tech/blog/private-location-journal-iphone/#why-private) -- [A simple setup checklist](https://isome.isolated.tech/blog/private-location-journal-iphone/#setup) -- [Capture visits and routes](https://isome.isolated.tech/blog/private-location-journal-iphone/#capture) -- [Choose a battery tradeoff](https://isome.isolated.tech/blog/private-location-journal-iphone/#battery) -- [Review the map locally](https://isome.isolated.tech/blog/private-location-journal-iphone/#review) -- [Export without lock-in](https://isome.isolated.tech/blog/private-location-journal-iphone/#export) -- [Back up and restore](https://isome.isolated.tech/blog/private-location-journal-iphone/#backup) -- [Use webhooks carefully](https://isome.isolated.tech/blog/private-location-journal-iphone/#webhooks) -- [Build durable habits](https://isome.isolated.tech/blog/private-location-journal-iphone/#habits) +- [Why keep it private?](https://isome.isolated.tech/blog/private-location-journal-iphone/#why-private) +- [A simple setup checklist](https://isome.isolated.tech/blog/private-location-journal-iphone/#setup) +- [Capture visits and routes](https://isome.isolated.tech/blog/private-location-journal-iphone/#capture) +- [Choose a battery tradeoff](https://isome.isolated.tech/blog/private-location-journal-iphone/#battery) +- [Review the map locally](https://isome.isolated.tech/blog/private-location-journal-iphone/#review) +- [Export without lock-in](https://isome.isolated.tech/blog/private-location-journal-iphone/#export) +- [Back up and restore](https://isome.isolated.tech/blog/private-location-journal-iphone/#backup) +- [Use webhooks carefully](https://isome.isolated.tech/blog/private-location-journal-iphone/#webhooks) +- [Build durable habits](https://isome.isolated.tech/blog/private-location-journal-iphone/#habits) -iso.me records your own location history while tracking is enabled. Start recording before the part of the day you want to keep, then review the map and Timeline. Installing the app cannot recover routes from before you recorded them. If you already use Google Timeline, [compare the two workflows](https://isome.isolated.tech/compare/google-maps-timeline/) before switching. +iso.me records your own location history while tracking is enabled. Start recording before the part of the day you want to keep, then review the map and Timeline. Installing the app cannot recover routes from before you recorded them. If you already use Google Timeline, [compare the two workflows](https://isome.isolated.tech/compare/google-maps-timeline/) before switching. ![iso.me map showing visits and recorded route points in San Francisco](https://isome.isolated.tech/blog/private-location-journal-iphone/screenshots/map.png) -Map view: visits, route dots, and route lines stay in a private timeline. +Map view: visits, route dots, and route lines stay in a private timeline. ![iso.me export screen showing JSON CSV Markdown GPX KML GeoJSON and webhook options](https://isome.isolated.tech/blog/private-location-journal-iphone/screenshots/export.png) -Export view: choose formats, data types, folders, and optional webhook destinations. +Export view: choose formats, data types, folders, and optional webhook destinations. ![iso.me settings screen with tracking permission distance filter stop after and location names controls](https://isome.isolated.tech/blog/private-location-journal-iphone/screenshots/settings.png) -Settings view: control tracking, permission state, distance filters, auto-stop, and naming. +Settings view: control tracking, permission state, distance filters, auto-stop, and naming. ## Why a private location journal is different -Most people do not need location history because they want another dashboard. They need it because memory is imperfect. Where did we park near the pier? Which route did that walk take? What day did I visit that client site? Which neighborhood did I pass through on the way to dinner? A local journal answers those questions without requiring every coordinate to become part of someone else's infrastructure. +Most people do not need location history because they want another dashboard. They need it because memory is imperfect. Where did we park near the pier? Which route did that walk take? What day did I visit that client site? Which neighborhood did I pass through on the way to dinner? A local journal answers those questions without requiring every coordinate to become part of someone else's infrastructure. -That distinction matters because location data is sensitive. A timeline can reveal your home, routines, work patterns, health visits, travel, religious practice, relationships, and habits. Before turning on any location recorder, ask two questions: who stores the data, and how do I leave with a copy? +That distinction matters because location data is sensitive. A timeline can reveal your home, routines, work patterns, health visits, travel, religious practice, relationships, and habits. Before turning on any location recorder, ask two questions: who stores the data, and how do I leave with a copy? -iso.me is built around the local-first answer. Your visits and routes are stored on your iPhone for core tracking. There is no iso.me account requirement and no iso.me server-side location archive for your everyday journal. If you enable features that talk to the network, such as readable place-name lookup through Apple's geocoding service or optional webhooks that you configure, review their boundaries. First-party onboarding and purchase telemetry is on by default and excludes location records; [the privacy policy lists network requests](https://isome.isolated.tech/privacy). +iso.me is built around the local-first answer. Your visits and routes are stored on your iPhone for core tracking. There is no iso.me account requirement and no iso.me server-side location archive for your everyday journal. If you enable features that talk to the network, such as readable place-name lookup through Apple's geocoding service or optional webhooks that you configure, review their boundaries. First-party onboarding and purchase telemetry is on by default and excludes location records; [the privacy policy lists network requests](https://isome.isolated.tech/privacy). ## A simple private-journal checklist -Permission Grant only the location access you are comfortable with. You can revisit iOS Settings later. +Permission Grant only the location access you are comfortable with. You can revisit iOS Settings later. -Tracking mode Start enables both visit monitoring and GPS recording. Stop ends both; there is no separate passive visit-only switch. +Tracking mode Start enables both visit monitoring and GPS recording. Stop ends both; there is no separate passive visit-only switch. -Names Use location names when readable places are helpful; remember geocoding is a network lookup handled by Apple. +Names Use location names when readable places are helpful; remember geocoding is a network lookup handled by Apple. -Export habit Keep periodic files in formats you can read later: JSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, or Overland. +Export habit Keep periodic files in formats you can read later: JSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, or Overland. -Automation boundary Configure webhooks only for self-hosted or trusted endpoints, and assume anything you send is no longer only on-device. +Automation boundary Configure webhooks only for self-hosted or trusted endpoints, and assume anything you send is no longer only on-device. -Deletion Know how to remove local history and remember that deleting an app can remove local-only data unless you exported it first. +Deletion Know how to remove local history and remember that deleting an app can remove local-only data unless you exported it first. ### Verify your first recording -- Open iso.me and finish setup. Choose While Using for manual sessions, or Always if you want automatic visits in the background. You can revisit this in iOS Settings. -- On the Map tab, start a short route with the recording control. Stop it when you finish. -- Open Timeline and check the date, route, and start/end times. Automatic visits need time at a place; do not expect every brief stop to appear immediately. -- If the result is empty, check location permission, tracking state, and the selected day before relying on a longer recording. +- Open iso.me and finish setup. Choose Always if you want GPS and visit monitoring to continue in the background; While Using limits when the app can obtain locations. You can revisit this in iOS Settings. +- On the Map tab, start a short route with the recording control. Stop it when you finish. +- Open Timeline and check the date, route, and start/end times. Automatic visits need time at a place; do not expect every brief stop to appear immediately. +- If the result is empty, check location permission, tracking state, and the selected day before relying on a longer recording. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-private-journal&mt=8) Tracking is free. Writing export files, scheduled exports, and webhooks require the one-time unlock; importing a prior export is free. See [current pricing](https://isome.isolated.tech/#pricing) and the [setup reference](https://isome.isolated.tech/docs/getting-started/). +[Record your first day free](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-private-journal&mt=8) + ## Capture visits and routes without turning your life into a feed -A good location journal has two layers: places and paths. Places are the stops you care about: a restaurant, hotel, trailhead, client site, beach, school, or errand. Paths are the routes between them: a hike, commute, road trip, city walk, bike ride, or site visit. +A good location journal has two layers: places and paths. Places are the stops you care about: a restaurant, hotel, trailhead, client site, beach, school, or errand. Paths are the routes between them: a hike, commute, road trip, city walk, bike ride, or site visit. -Visits and route points describe different parts of your day, but they share the same recording controls. Start enables visit monitoring, significant location changes, and detailed GPS recording together. Stop ends all three. Always location permission allows recording in the background; visits can arrive later than the route points around them. +Visits and route points describe different parts of your day, but they share the same recording controls. Start enables visit monitoring, significant location changes, and detailed GPS recording together. Stop ends all three. Always location permission allows recording in the background; visits can arrive later than the route points around them. -- Start tracking before the period you want to remember. Leaving the app installed alone does not record a day. -- Open Timeline after recording to check the date, route, and detected visits. Add or correct a visit if needed. -- Use auto-stop settings as a safety net so precise tracking does not run longer than intended. +- Start tracking before the period you want to remember. Leaving the app installed alone does not record a day. +- Open Timeline after recording to check the date, route, and detected visits. Add or correct a visit if needed. +- Use auto-stop settings as a safety net so precise tracking does not run longer than intended. ## Choose a battery tradeoff Visit monitoring and detailed GPS run together while tracking is on. Stop recording when you finish, or choose an auto-stop timer. High-accuracy GPS uses battery; there is no universal battery-life promise. -- For a walk or trip, start a route deliberately and stop it when finished. -- Try a 25–50 meter distance filter for a longer day, then inspect a short test route. A larger filter can reduce detail; choose it for your use case rather than assuming maximum precision is always better. -- Set an auto-stop timer as a fallback. Check that the timer will not end before a route you intend to keep. -- If history has gaps, check permission and recording state. Battery-saving settings cannot recover points that were never captured. +- For a walk or trip, start a route deliberately and stop it when finished. +- Try a 25–50 meter distance filter for a longer day, then inspect a short test route. A larger filter can reduce detail; choose it for your use case rather than assuming maximum precision is always better. +- Set an auto-stop timer as a fallback. Check that the timer will not end before a route you intend to keep. +- If history has gaps, check permission and recording state. Battery-saving settings cannot recover points that were never captured. Use the [battery-use checklist](https://isome.isolated.tech/blog/iphone-location-tracking-battery/) to compare settings on your phone. The [tracking reference](https://isome.isolated.tech/docs/tracking/) lists the available controls. ## Review your map locally first -The map is the fastest way to make the journal feel real. You can scan where you stopped, see route lines, and connect points to the day they happened. This is useful even when you never export anything. The app becomes a private memory instrument: open it, answer a question, close it. +The map is the fastest way to make the journal feel real. You can scan where you stopped, see route lines, and connect points to the day they happened. This is useful even when you never export anything. The app becomes a private memory instrument: open it, answer a question, close it. -When readable place names help, iso.me can use Apple's geocoding service to turn coordinates into names or addresses. That makes the timeline easier to read, but it is still worth understanding the boundary: coordinate-to-place lookup is a network service governed by Apple's policies, not an iso.me location database. +When readable place names help, iso.me can use Apple's geocoding service to turn coordinates into names or addresses. That makes the timeline easier to read, but it is still worth understanding the boundary: coordinate-to-place lookup is a network service governed by Apple's policies, not an iso.me location database. -Storage and network requests +Storage and network requests Your journal is stored locally. Apple services can receive coordinates for place names and map features, and optional webhooks deliver records to your endpoint. Check the [privacy policy](https://isome.isolated.tech/privacy) before choosing a workflow. ## Export without locking your memory inside one app -A private journal is only truly yours if you can leave with a copy. iso.me's export workflow is designed for that: visits, route points, or both can be prepared as files you understand and can keep elsewhere. +A private journal is only truly yours if you can leave with a copy. iso.me's export workflow is designed for that: visits, route points, or both can be prepared as files you understand and can keep elsewhere. + +The most human-readable path is Markdown. The most spreadsheet-friendly path is CSV. The most tool-friendly path is JSON. For maps and location tools, formats such as GPX, KML, and GeoJSON are useful because other software already knows how to draw or process them. The current app also exposes location-history formats such as OwnTracks and Overland for people who already use those ecosystems. -The most human-readable path is Markdown. The most spreadsheet-friendly path is CSV. The most tool-friendly path is JSON. For maps and location tools, formats such as GPX, KML, and GeoJSON are useful because other software already knows how to draw or process them. The current app also exposes location-history formats such as OwnTracks and Overland for people who already use those ecosystems. +- Use Markdown for a journal-like archive you can read in any notes app. +- Use CSV when you want rows, filters, and spreadsheets. +- Use JSON when you want structured data for scripts or backups. +- Use GPX, KML, or GeoJSON when you want routes and points in mapping tools. -- Use Markdown for a journal-like archive you can read in any notes app. -- Use CSV when you want rows, filters, and spreadsheets. -- Use JSON when you want structured data for scripts or backups. -- Use GPX, KML, or GeoJSON when you want routes and points in mapping tools. +Exported files are powerful because they leave the app boundary. Store them deliberately. If you put them in cloud storage, email them, or import them into another service, that copy follows the privacy rules of the place you sent it. -Exported files are powerful because they leave the app boundary. Store them deliberately. If you put them in cloud storage, email them, or import them into another service, that copy follows the privacy rules of the place you sent it. +For a travel summary, [Country Days shows the local dates behind each country total](https://isome.isolated.tech/blog/track-days-in-country-iphone/), including manual stays for gaps. ## Keep a backup you can restore Export visits and route points as iso.me JSON when your goal is to import those records later. Keep each generated file. GPX and KML are useful for map viewers, but cannot be imported back into iso.me. Do not assume that a file preserves every app setting or outing edit. -- In Export, choose visits, JSON, and the date range you need; export that file. Repeat for route points and keep both files. Review filters and field choices that might exclude required records. -- Use Preview to check the result, then export to a folder you control. Writing the file requires export access; Preview is free. -- Open Files and confirm the JSON exists and contains the expected date range. Keep a separate copy before replacing your phone or deleting iso.me. -- To restore a prior export, open Settings → Import file and select your saved JSON. Review the import result, then check several dates in Timeline and the map before treating recovery as complete. +- In Export, choose visits, JSON, and the date range you need; export that file. Repeat for route points and keep both files. Review filters and field choices that might exclude required records. +- Use Preview to check the result, then export to a folder you control. Writing the file requires export access; Preview is free. +- Open Files and confirm the JSON exists and contains the expected date range. Keep a separate copy before replacing your phone or deleting iso.me. +- To restore a prior export, open Settings → Import file and select your saved JSON. Review the import result, then check several dates in Timeline and the map before treating recovery as complete. Keep your original backup during recovery. A filtered export contains only the selected data, and import cannot restore records absent from that file. Follow [the full backup and restore checklist](https://isome.isolated.tech/blog/back-up-iphone-location-history/), or see [export and import](https://isome.isolated.tech/docs/export-import/) for supported formats and [automatic exports](https://isome.isolated.tech/docs/automatic-exports/) for scheduled copies. @@ -154,32 +158,32 @@ Content reviewed October 26, 2026 against the product source and documentation. ## Use optional webhooks carefully -Some people want a private journal that also feeds a self-hosted archive, a home server, or a custom automation. iso.me includes webhook settings for users who want to post selected location data to an HTTP endpoint in real time or batches. +Some people want a private journal that also feeds a self-hosted archive, a home server, or a custom automation. iso.me includes webhook settings for users who want to post selected location data to an HTTP endpoint in real time or batches. -This is intentionally an advanced feature. A webhook changes the privacy model because data leaves the phone and lands wherever the endpoint is hosted. That can be exactly what you want if you run the server, understand the logs, and control retention. It is not the same as keeping everything only on the device. +This is intentionally an advanced feature. A webhook changes the privacy model because data leaves the phone and lands wherever the endpoint is hosted. That can be exactly what you want if you run the server, understand the logs, and control retention. It is not the same as keeping everything only on the device. -- Prefer self-hosted or trusted endpoints. -- Use authentication for endpoints that support it. -- Send only the data type you need, not everything by default. -- Check the receiving service's backups, logs, and retention policy. +- Prefer self-hosted or trusted endpoints. +- Use authentication for endpoints that support it. +- Send only the data type you need, not everything by default. +- Check the receiving service's backups, logs, and retention policy. ## Choose your next task - Looking for an earlier visit? [Check existing iPhone location history](https://isome.isolated.tech/blog/view-location-history-iphone/) before starting a new recording. -- Need a portable path? [Record a route and export GPX](https://isome.isolated.tech/blog/record-iphone-route-gpx/), with a sample file and troubleshooting. +- Need a portable path? [Record a route and export GPX](https://isome.isolated.tech/blog/record-iphone-route-gpx/), with a sample file and troubleshooting. ## Build habits that keep the journal useful -The best private archive is boring in the right ways. Check the settings once in a while. Confirm location permission still matches your intent. Export before wiping a device or deleting the app. Keep a periodic backup if the history matters. Delete old data when it no longer serves you. +The best private archive is boring in the right ways. Check the settings once in a while. Confirm location permission still matches your intent. Export before wiping a device or deleting the app. Keep a periodic backup if the history matters. Delete old data when it no longer serves you. -Also be honest about what a location journal is not. It is not tax advice, legal advice, or a guarantee that every movement was captured perfectly. GPS can be noisy, permissions can change, devices can be offline, and batteries can die. Treat your timeline as a memory and records aid, not as authoritative proof for a situation that needs a professional standard. +Also be honest about what a location journal is not. It is not tax advice, legal advice, or a guarantee that every movement was captured perfectly. GPS can be noisy, permissions can change, devices can be offline, and batteries can die. Treat your timeline as a memory and records aid, not as authoritative proof for a situation that needs a professional standard. -Used that way, a private location journal is quietly valuable. It gives you the personal benefits of remembering places and routes while avoiding the default assumption that your location history has to live in a giant remote account forever. +Used that way, a private location journal is quietly valuable. It gives you the personal benefits of remembering places and routes while avoiding the default assumption that your location history has to live in a giant remote account forever. ## Start with a local journal. Download iso.me, keep your working location history on your iPhone, and export when you need a portable copy. -[Get iso.me](https://apps.apple.com/us/app/iso-me/id6761960794) +[Get iso.me](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-private-journal&mt=8) Source: https://isome.isolated.tech/blog/private-location-journal-iphone/ diff --git a/marketing/public/_markdown/blog/record-iphone-route-gpx/index.md b/marketing/public/_markdown/blog/record-iphone-route-gpx/index.md index 465d254c..22bc4566 100644 --- a/marketing/public/_markdown/blog/record-iphone-route-gpx/index.md +++ b/marketing/public/_markdown/blog/record-iphone-route-gpx/index.md @@ -25,10 +25,10 @@ From recording to file ## 1. Record a short route -- Open iso.me and complete permission setup. Choose Always location access if you want recording to continue in the background. -- On the Map tab, start recording before you leave. Start enables GPS recording, visit monitoring, and significant location changes together. -- After a short walk or trip, stop recording. Stop ends both GPS and visit monitoring. -- Open Timeline and check the outing’s date, start and end times, and map. Confirm that it contains the part of the trip you intend to export. +- Open iso.me and complete permission setup. Choose Always location access if you want recording to continue in the background. +- On the Map tab, start recording before you leave. Start enables GPS recording, visit monitoring, and significant location changes together. +- After a short walk or trip, stop recording. Stop ends both GPS and visit monitoring. +- Open Timeline and check the outing’s date, start and end times, and map. Confirm that it contains the part of the trip you intend to export. Try this with a short session before relying on it for a full day. GPS can be noisy or unavailable, and permission changes or a stopped session can leave gaps. There is no separate passive visit-only switch. The [recording reference](https://isome.isolated.tech/docs/tracking/) explains distance filtering and auto-stop. @@ -36,19 +36,19 @@ For a longer trip, choose an auto-stop duration that will not end early. Stop wh ## 2. Choose Points and GPX -- Open Export and choose Points as the data type. These are the recorded GPS locations that make up a path. -- Select GPX. If other formats are also selected, the export can produce additional files. -- Choose the date range for your recording. Review any time-of-day, accuracy, and GPS-glitch filters that could exclude points. -- Open Preview. Check the intended date and file contents before paying for or writing an export. -- Export. With a default folder configured, look there for the saved file; otherwise use the share sheet to save it in Files. +- Open Export and choose Points as the data type. These are the recorded GPS locations that make up a path. +- Select GPX. If other formats are also selected, the export can produce additional files. +- Choose the date range for your recording. Review any time-of-day, accuracy, and GPS-glitch filters that could exclude points. +- Open Preview. Check the intended date and file contents before paying for or writing an export. +- Export. With a default folder configured, look there for the saved file; otherwise use the share sheet to save it in Files. You can also open a specific outing in Timeline and use its Export action with GPX selected. For a full reference on filenames, date filters, and saving destinations, see [export and restore compatibility](https://isome.isolated.tech/docs/export-import/). -Choose the data you actually need -| Choice | GPX result | Use it for -| Points | Track points grouped into track segments | The recorded path over a selected period -| Visits | Waypoints, when visit coordinates are included | Stops rather than a continuous path -| Outings | The selected outing’s route points | A particular recorded trip +Choose the data you actually need +| Choice | GPX result | Use it for +| Points | Track points grouped into track segments | The recorded path over a selected period +| Visits | Waypoints, when visit coordinates are included | Stops rather than a continuous path +| Outings | The selected outing’s route points | A particular recorded trip A GPX export with only visits can be valid but show pins instead of a line. Pick Points or an outing if the path is the part you want to keep. @@ -60,10 +60,10 @@ The export interface. This screenshot illustrates the workflow and may show samp Find the exported `.gpx` file in the folder you chose. Confirm the filename and date before sending it elsewhere. If your destination application accepts GPX tracks, use its import or open-file action to select the file. -- Check that the track covers the expected start and end locations. -- Check timestamps against the trip. GPX times may be shown in UTC or converted to the viewer’s local timezone. -- Look for gaps and separate segments instead of assuming every straight line represents captured movement. -- Keep the original file if another tool rewrites or converts it. +- Check that the track covers the expected start and end locations. +- Check timestamps against the trip. GPX times may be shown in UTC or converted to the viewer’s local timezone. +- Look for gaps and separate segments instead of assuming every straight line represents captured movement. +- Keep the original file if another tool rewrites or converts it. GPX describes geographic data; it does not include a street map or guarantee that every app offers the same display. Files preview may show text or a file icon rather than drawing a route. A viewer that supports waypoints alone may not display a track. @@ -85,11 +85,11 @@ The coordinates identify a point. Its time helps a viewer place it in sequence; For an incomplete iso.me day, use the [missing visits and route points checklist](https://isome.isolated.tech/blog/missing-location-history-iphone/) to distinguish recording, display, Watch sync, and export issues. -- No points in Preview: check the selected dates and filters, then open the same day in Timeline. Export cannot create a path that was not recorded. -- Pins instead of a line: check whether you exported Visits rather than Points. -- The path has gaps: check recording state, permission, and auto-stop. Inspect the original points before changing filters to include less accurate fixes. -- File saved somewhere unexpected: check the default export folder before repeating the export. Some exports produce more than one file. -- A viewer rejects the file: confirm it supports GPX 1.1 tracks and that the file was completely saved. Keep the original while checking the error. +- No points in Preview: check the selected dates and filters, then open the same day in Timeline. Export cannot create a path that was not recorded. +- Pins instead of a line: check whether you exported Visits rather than Points. +- The path has gaps: check recording state, permission, and auto-stop. Inspect the original points before changing filters to include less accurate fixes. +- File saved somewhere unexpected: check the default export folder before repeating the export. Some exports produce more than one file. +- A viewer rejects the file: confirm it supports GPX 1.1 tracks and that the file was completely saved. Keep the original while checking the error. ## Keep a separate copy for restoring your journal @@ -104,7 +104,7 @@ Choose how to keep it. Try free recording and export preview. The optional purchase unlocks writing files; see [current pricing](https://isome.isolated.tech/#pricing). -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-gpx&mt=8) Reviewed October 26, 2026. Steps reflect iso.me’s recording and export controls; labels can vary by app version. For setup, read [the private journal guide](https://isome.isolated.tech/blog/private-location-journal-iphone/); for existing Apple or Google records, see [how to view iPhone location history](https://isome.isolated.tech/blog/view-location-history-iphone/). diff --git a/marketing/public/_markdown/blog/track-days-in-country-iphone/index.md b/marketing/public/_markdown/blog/track-days-in-country-iphone/index.md new file mode 100644 index 00000000..dda539e6 --- /dev/null +++ b/marketing/public/_markdown/blog/track-days-in-country-iphone/index.md @@ -0,0 +1,96 @@ +- [iso.me](https://isome.isolated.tech/) +- [Guides](https://isome.isolated.tech/blog/) +- Country days + +Practical iPhone guides + +# How to track days spent in each country on iPhone + +Review country totals and the dates behind them, add missing stays, and keep a personal record without an iso.me account. + +By [Cody Bontecou](https://isolated.tech), iso.me’s developer · Reviewed October 26, 2026 + +## Count the dates you can account for + +In iso.me, open Timeline → Country Days to count local dates represented by your recorded visits, route points, and manual stays. Choose this year, the last 365 days, or all time, then open a country to review its dates. Viewing the counts and adding manual stays are free. Writing the CSV file requires the optional export purchase. + +This guide covers Country Days in iso.me 1.7.16. It is a personal travel journal: its rules do not determine tax residency, immigration status, or how a visa counts a day. + +Build your country record +- [Open your country totals](https://isome.isolated.tech/blog/track-days-in-country-iphone/#start) +- [Understand travel days and timezones](https://isome.isolated.tech/blog/track-days-in-country-iphone/#rules) +- [Add a missing stay](https://isome.isolated.tech/blog/track-days-in-country-iphone/#manual) +- [Identify countries in older records](https://isome.isolated.tech/blog/track-days-in-country-iphone/#privacy) +- [Save a CSV copy](https://isome.isolated.tech/blog/track-days-in-country-iphone/#csv) + +## 1. Review the dates behind each total + +- Open Timeline, then Country Days. +- Select a period. The default is this year; the other choices are the last 365 days and all time. +- Open a country and review the individual dates. A total is only useful when you understand which dates produced it. +- If older locations lack countries, use the analysis controls described below. If nothing was recorded for a stay, add it manually rather than expecting GPS to recreate it. + +To collect new history, start recording before your trip. Start enables detailed GPS and visit monitoring together; Stop ends both. Read [the first-recording guide](https://isome.isolated.tech/blog/private-location-journal-iphone/) for permissions and recording controls. + +![Country Days on iPhone, with period filters, country analysis, and Add stay controls](https://isome.isolated.tech/screenshots/country-days.webp) + +Country Days before any country dates have been resolved. Captured in development build 1.7.17 (47), in an iOS 26.5 simulator on October 26, 2026; this is an interface example, not a recorded trip. + +## 2. Check the counting rules + +Presence dates, rather than a continuous travel guarantee +| Situation | How iso.me counts it +| Many points in the same country on one date | One day for that country, rather than one day per record. +| Two countries on a travel day | That date can count in both countries. Adding country totals may exceed the number of distinct dates. +| A record near midnight | The resolved location’s timezone determines the local date, rather than UTC or your phone’s current timezone. +| A completed visit with a verified departure | Its local date range can contribute multiple dates. +| An open visit or unverified departure | Only its arrival date is counted. Route points or manual stays can account for other dates. +| Unknown country, GPS outlier, or recording gap | No invented dates or automatic continuous stay. +| Overlapping manual and recorded presence | The date counts once per country; the source flags can show both. + +### A simple border-crossing example + +Imagine a recorded point in Portugal on October 1 and another in Spain later that local date. Each country gets October 1. If a manual Portugal stay also includes October 1, Portugal still gets one day. If October 2 has no usable evidence or manual stay, the app does not fill it merely because you have records before and after it. + +This is an invented example of the counting rules, not a captured trip. Review gaps with the [missing-records checklist](https://isome.isolated.tech/blog/missing-location-history-iphone/) before changing your journal. + +## 3. Add a stay that was not recorded + +Use Add stay in Country Days. Choose the country and first and last dates, add an optional note, and save. Review the affected country’s dates afterwards. You can edit or delete a manual stay when you find a mistake. + +A manual stay records your account of a trip; it does not create a GPS path. Keep tickets or other original records separately if you need them. Overlapping manual stays do not multiply the same country/date. + +## 4. Identify countries in older locations + +New recordings identify countries when network geocoding is enabled. Analyze saved locations checks earlier records in batches, with stop and resume controls. It can take time for a large archive. + +Country identification uses Apple geocoding and follows your network-geocoding preference. A lookup sends coordinates to Apple; turning it off changes which unresolved locations can be assigned a country. Your journal remains on your device, and iso.me does not receive an archive of it. See the [privacy policy](https://isome.isolated.tech/privacy) for all network boundaries. + +Analysis can identify a country for an existing coordinate. It cannot recover locations that were never recorded. Use a manual stay for dates you can account for independently. + +## 5. Keep a CSV copy of your country dates + +Use the export control in Country Days and save the CSV to a destination you choose. The file includes country codes, local dates, and recorded/manual source information. Viewing and editing your counts are free; writing this export requires the lifetime unlock. See [current pricing](https://isome.isolated.tech/#pricing). + +Check a known date and a travel day in the saved file. A country-date CSV is a summary, not a backup of every visit, route point, or manual stay. Keep your underlying records using the [backup checklist](https://isome.isolated.tech/blog/back-up-iphone-location-history/). + +## Remember the country. +Keep the dates behind the count. + +Start a free local journal and review Country Days on your iPhone. + +[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) + +Reviewed October 26, 2026 against the source used for App Store 1.7.16 build 46, including CountryDaysView, CountryDayCalculator, and CountryDayResolver. The examples are synthetic. They do not represent a new physical travel test. + +## Read next + +- [Record your next trip](https://isome.isolated.tech/blog/private-location-journal-iphone/) + +Start a local journal before you leave. + +- [Keep the underlying records](https://isome.isolated.tech/blog/back-up-iphone-location-history/) + +A country-date summary is not a complete backup. + +Source: https://isome.isolated.tech/blog/track-days-in-country-iphone/ diff --git a/marketing/public/_markdown/blog/view-location-history-iphone/index.md b/marketing/public/_markdown/blog/view-location-history-iphone/index.md index 949bdbc5..412a99db 100644 --- a/marketing/public/_markdown/blog/view-location-history-iphone/index.md +++ b/marketing/public/_markdown/blog/view-location-history-iphone/index.md @@ -24,20 +24,20 @@ Choose your next step ## Which history are you looking for? -Start with the service that recorded the day -| What you used | Where to look | What to check -| Apple Maps | Places → Visited Places, where available | Whether the feature was enabled and the visit is retained -| Google Maps | Profile picture → Your Timeline | The account, selected device history, and date -| iso.me | Timeline or the date range on Map | Whether tracking was enabled for that period -| No enabled recorder | There may be no route record to open | Start a new recording before the next trip +Start with the service that recorded the day +| What you used | Where to look | What to check +| Apple Maps | Places → Visited Places, where available | Whether the feature was enabled and the visit is retained +| Google Maps | Profile picture → Your Timeline | The account, selected device history, and date +| iso.me | Timeline or the date range on Map | Whether tracking was enabled for that period +| No enabled recorder | There may be no route record to open | Start a new recording before the next trip Directions you requested, places you searched for, and a recorded visit are different kinds of information. A search for a restaurant does not by itself establish when you arrived or how you travelled there. ## Find visited places in Apple Maps -- Open Maps, then open Places. -- Choose Visited Places, if it is available. -- Search for a place or filter by date, category, or city. Use All Visits to browse. +- Open Maps, then open Places. +- Choose Visited Places, if it is available. +- Search for a place or filter by date, category, or city. Use All Visits to browse. Apple says this feature needs to be enabled before visits appear, is unavailable in some regions, and keeps visits encrypted so Apple cannot read them. Retention settings can also remove older entries. Menus vary with iOS version; use [Apple’s Visited Places instructions](https://support.apple.com/guide/iphone/view-visited-places-iph0c2597c4f/ios) for your version. @@ -45,22 +45,22 @@ If you are looking for a setting called Significant Locations rather than a Maps ## Open Google Maps Timeline -- Open Google Maps and tap your profile picture or initial. -- Choose Your Timeline, then use the calendar to select a day. -- If history is missing, confirm which account and device you used. Check your backup and deletion settings before making changes. +- Open Google Maps and tap your profile picture or initial. +- Choose Your Timeline, then use the calendar to select a day. +- If history is missing, confirm which account and device you used. Check your backup and deletion settings before making changes. Google Timeline stores history on the device and can keep an encrypted backup. To save an independent archive, Google’s iPhone instructions use Settings → Location & Privacy → Export Timeline data, then Save to Files. Settings are changing, so follow [Google’s current Timeline guide](https://support.google.com/maps/answer/6258979?co=GENIE.Platform%3DiOS&hl=en) if your menus differ. -Keep that archive separately. iso.me does not import Google Timeline files; the [Google Timeline comparison](https://isome.isolated.tech/compare/google-maps-timeline/) explains the tradeoffs before you change your recording setup. +Keep that archive separately. The verified App Store 1.7.16 build does not import Google Timeline files; the [Google Timeline comparison](https://isome.isolated.tech/compare/google-maps-timeline/) explains the tradeoffs before you change your recording setup. ## Why a day can be empty First check the date, account, and app rather than assuming the history is gone. A map showing today may simply be the wrong view for last month’s trip. In iso.me, use Timeline’s date controls or change the Map date range. -- Recording was off. A location permission lets an app request locations; it is not proof that the app recorded that day. -- The record was removed. Look for retained files or supported backups before clearing more data or replacing a device. -- The device missed part of the trip. Permission changes, a stopped session, GPS conditions, or a flat battery can leave gaps. -- A visit has not appeared. Detected arrivals and departures are not an immediate check-in at every stop. A route can contain points even when a visit is missing. +- Recording was off. A location permission lets an app request locations; it is not proof that the app recorded that day. +- The record was removed. Look for retained files or supported backups before clearing more data or replacing a device. +- The device missed part of the trip. Permission changes, a stopped session, GPS conditions, or a flat battery can leave gaps. +- A visit has not appeared. Detected arrivals and departures are not an immediate check-in at every stop. A route can contain points even when a visit is missing. For an incomplete iso.me day, use the [missing visits and route points checklist](https://isome.isolated.tech/blog/missing-location-history-iphone/) to distinguish recording, display, Watch sync, and export issues. @@ -70,10 +70,10 @@ Photos, receipts, and calendar entries may help you remember a day, but they are If you want a separate journal without an iso.me account, try a short recording before a longer trip: -- Install iso.me and complete permission setup. Always location access allows recording in the background. -- On Map, tap the recording control before you leave. Start enables GPS recording and visit monitoring together. -- Stop when you finish. Open Timeline and check the date, route, and times. -- If you need a portable route file, follow [the iPhone route and GPX guide](https://isome.isolated.tech/blog/record-iphone-route-gpx/). +- Install iso.me and complete permission setup. Always location access allows recording in the background. +- On Map, tap the recording control before you leave. Start enables GPS recording and visit monitoring together. +- Stop when you finish. Open Timeline and check the date, route, and times. +- If you need a portable route file, follow [the iPhone route and GPX guide](https://isome.isolated.tech/blog/record-iphone-route-gpx/). Recording and reviewing your journal are free. Writing export files requires the optional one-time unlock; preview is free. Read [the setup walkthrough](https://isome.isolated.tech/blog/private-location-journal-iphone/) for permissions, battery controls, and keeping supported copies. @@ -88,7 +88,7 @@ Start recording before you go. Try iso.me’s free recording, then review the route and visits on your iPhone. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) Reviewed October 26, 2026 against Apple and Google documentation and iso.me’s product source. Platform instructions can vary by version and region. Written by iso.me’s developer; the screenshots are interface examples. diff --git a/marketing/public/_markdown/compare/google-maps-timeline/index.md b/marketing/public/_markdown/compare/google-maps-timeline/index.md index 45c7be22..482f8ea7 100644 --- a/marketing/public/_markdown/compare/google-maps-timeline/index.md +++ b/marketing/public/_markdown/compare/google-maps-timeline/index.md @@ -18,27 +18,27 @@ Google Timeline already keeps history on your device and offers encrypted backup ## Compare the everyday workflow -iPhone location history: accounts, recording, and portability -| Question | iso.me | Google Timeline -| Account | No iso.me account. | Google account. -| Storage and backup | Local journal. Keep supported export files for restoration; no built-in cloud sync. | Device history, with optional encrypted server backup. -| Recording | Start and Stop control GPS recording and visit monitoring together. Always permission allows background recording. | Visits and routes collected with Timeline enabled. -| Files | JSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, and Overland. Paid export; free preview. | Location-history JSON export. -| Moving existing history | Imports supported iso.me visit and point files. No Google Timeline importer. | Timeline backup can transfer history to another device. -| Payment | Free recording. US lifetime unlock: $19.99 Individual or $39.99 Family. Regional prices vary. | Timeline is available within Google Maps. +iPhone location history: accounts, recording, and portability +| Question | iso.me | Google Timeline +| Account | No iso.me account. | Google account. +| Storage and backup | Local journal. Keep supported export files for restoration; no built-in cloud sync. | Device history, with optional encrypted server backup. +| Recording | Start and Stop control GPS recording and visit monitoring together. Always permission allows background recording. | Visits and routes collected with Timeline enabled. +| Files | JSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, and Overland. Paid export; free preview. | Location-history JSON export. +| Moving existing history | App Store 1.7.16 imports iso.me JSON, CSV, and Markdown files. No Google Timeline import in that build. | Timeline backup can transfer history to another device. +| Payment | Free recording. US lifetime unlock: $19.99 Individual or $39.99 Family. Regional prices vary. | Timeline is available within Google Maps. Google features: [Google’s Timeline help for iPhone](https://support.google.com/maps/answer/6258979?co=GENIE.Platform%3DiOS&hl=en), checked October 26, 2026. iso.me features are described in its [product documentation](https://isome.isolated.tech/docs/). This comparison is written by iso.me’s developer. ## When iso.me fits -- You want a personal route and visit journal without creating another account. -- You want to choose when recording starts and stops, review outings, and replay recorded routes. -- You need GPX for a route viewer, CSV for a spreadsheet, or Markdown for a readable archive. -- You want an optional webhook workflow alongside a local journal. +- You want a personal route and visit journal without creating another account. +- You want to choose when recording starts and stops, review outings, and replay recorded routes. +- You need GPX for a route viewer, CSV for a spreadsheet, or Markdown for a readable archive. +- You want an optional webhook workflow alongside a local journal. Use the [private location journal guide](https://isome.isolated.tech/blog/private-location-journal-iphone/) to set up your first recording. Start enables detailed GPS as well as visit monitoring; there is no separate passive visit-only switch. Permissions, GPS conditions, and battery can affect the record. -[Try free tracking on iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Try free tracking on iPhone](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-google-timeline&mt=8) ## When keeping Google Timeline makes sense @@ -48,7 +48,7 @@ If you want to try iso.me, record a short session and inspect it before relying ## Preserve your existing history first -Save Google’s exported archive separately before changing apps or devices. iso.me cannot import that archive or reconstruct earlier movement. +Save Google’s exported archive separately before changing apps or devices. App Store 1.7.16 cannot import that archive. A future importer still cannot reconstruct records missing from the file. For existing Apple or Google records, start with [the iPhone history guide](https://isome.isolated.tech/blog/view-location-history-iphone/). For new iso.me routes, follow [the GPX export walkthrough](https://isome.isolated.tech/blog/record-iphone-route-gpx/) and check [export and restore compatibility](https://isome.isolated.tech/docs/export-import/). A GPX file is useful for drawing a route elsewhere, but it cannot be imported into iso.me. Keep supported visit and point exports for records you want to restore later. @@ -60,14 +60,14 @@ Read the [privacy policy](https://isome.isolated.tech/privacy), [recording contr ![Example iso.me map interface with visit markers and recorded route points](https://isome.isolated.tech/screenshots/map-480.webp) -iso.me’s map interface. The screenshot is illustrative and may show sample data or earlier labels. +iso.me’s map interface. The screenshot is illustrative and may show sample data or earlier labels. ## Record your next route. Keep a copy you can use. Start with free tracking, then decide whether you need the optional export unlock. -[Download free for iPhone](https://apps.apple.com/us/app/iso-me/id6761960794) +[Download free for iPhone](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-google-timeline&mt=8) ## Read next diff --git a/marketing/public/_markdown/docs/apple-watch/index.md b/marketing/public/_markdown/docs/apple-watch/index.md index 46345afe..1253cad4 100644 --- a/marketing/public/_markdown/docs/apple-watch/index.md +++ b/marketing/public/_markdown/docs/apple-watch/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 10 of 11 +§ Docs · Guide 10 of 11 # Record Apple Watch GPS routes without your iPhone @@ -28,35 +28,35 @@ Install the Watch app and allow its location request. The phone app is needed to ## Before your first route -- Open iso.me on the Watch. If it asks for location access, respond to the permission prompt. If access was denied, review the Watch's location settings. -- Tap Start and confirm the status changes from standby to tracking. After an initial permission request, check the state rather than assuming a recording began. -- Try a short route first. Look for the elapsed time and point count to change before relying on a longer session. -- When finished, tap Stop on the Watch. Confirm it has left the tracking state. +- Open iso.me on the Watch. If it asks for location access, respond to the permission prompt. If access was denied, review the Watch's location settings. +- Tap Start and confirm the status changes from standby to tracking. After an initial permission request, check the state rather than assuming a recording began. +- Try a short route first. Look for the elapsed time and point count to change before relying on a longer session. +- When finished, tap Stop on the Watch. Confirm it has left the tracking state. Recording away from the phone is separate from syncing to it. You do not need an active phone connection for the Watch to collect points, but the phone must be available later for transfer. GPS conditions, permission, battery, and watchOS behavior can affect the recording. ## Sync and verify the result -- Bring the paired Watch and iPhone together and open iso.me on the iPhone. -- Open iso.me on the Watch. If available in your version, tap Sync Now and read the status. -- In the phone app, open Timeline for the day of the recording. Check the outing and use its map to inspect the expected points and times. -- Check both route points and visits. A transferred route is not proof that every stop was detected or named correctly. +- Bring the paired Watch and iPhone together and open iso.me on the iPhone. +- Open iso.me on the Watch. If available in your version, tap Sync Now and read the status. +- In the phone app, open Timeline for the day of the recording. Check the outing and use its map to inspect the expected points and times. +- Check both route points and visits. A transferred route is not proof that every stop was detected or named correctly. -Read the sync state before retrying -| Watch status | What to do next -| Connecting to iPhone | Keep the paired devices available and open the phone app. -| Sync queued | The request is queued. Check the phone result; this is not confirmation that every record is imported. -| Synced with iPhone | The phone acknowledged the delivered data. Still check the intended day and route. -| Nothing to sync | Check the phone's existing history and the selected day. An empty pending queue is not a full history report. +Read the sync state before retrying +| Watch status | What to do next +| Connecting to iPhone | Keep the paired devices available and open the phone app. +| Sync queued | The request is queued. Check the phone result; this is not confirmation that every record is imported. +| Synced with iPhone | The phone acknowledged the delivered data. Still check the intended day and route. +| Nothing to sync | Check the phone's existing history and the selected day. An empty pending queue is not a full history report. Completed transfers are acknowledged by the phone; points remain in the Watch queue until acknowledged. This helps retry delivery, but the queue is not a full backup of history already transferred. Do not uninstall the Watch app as a first troubleshooting step. ## If the route is missing or incomplete -- Nothing recorded: check the Watch's location permission, tracking state, and whether the point count advanced during the session. -- Watch has data, phone looks empty: check the recording date, open both apps, and read the Watch sync status before starting another route. -- Points arrived but visits differ: Watch visits are derived from recorded movement and are not identical to the iPhone's automatic visit detection. Check the route itself and correct places where needed. -- Older app version: an update can change sync behavior, but cannot recreate every record that is no longer retained. Keep existing data while diagnosing a gap. +- Nothing recorded: check the Watch's location permission, tracking state, and whether the point count advanced during the session. +- Watch has data, phone looks empty: check the recording date, open both apps, and read the Watch sync status before starting another route. +- Points arrived but visits differ: Watch visits are derived from recorded movement and are not identical to the iPhone's automatic visit detection. Check the route itself and correct places where needed. +- Older app version: an update can change sync behavior, but cannot recreate every record that is no longer retained. Keep existing data while diagnosing a gap. If a retry does not resolve it, contact support with the app versions, recording date, and exact sync message. You can describe the missing period without sending your private route. diff --git a/marketing/public/_markdown/docs/automatic-exports/index.md b/marketing/public/_markdown/docs/automatic-exports/index.md index 0f1e52d6..95756800 100644 --- a/marketing/public/_markdown/docs/automatic-exports/index.md +++ b/marketing/public/_markdown/docs/automatic-exports/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 7 of 11 +§ Docs · Guide 7 of 11 # Automatic exports @@ -28,14 +28,14 @@ You pick a folder, a format, and a schedule. Each run exports the current local ## Schedules -- Once daily — at a time you choose (default 21:00). -- Every 1–23 hours — from a start time you choose. A 3-hour schedule starting at 09:00 fires at 09:00, 12:00, 15:00…; intervals that don't divide the day simply restart from the next day's start time. +- Once daily — at a time you choose (default 21:00). +- Every 1–23 hours — from a start time you choose. A 3-hour schedule starting at 09:00 fires at 09:00, 12:00, 15:00…; intervals that don't divide the day simply restart from the next day's start time. ## Rewrite vs append -| Mode | Behavior -| Rewrite (default) | Each run rewrites the day's file with everything recorded so far today. Simple and self-healing. -| Append | Each run adds only records captured since the last successful run — no duplicates, tiny writes. (Once-daily schedules always rewrite.) +| Mode | Behavior +| Rewrite (default) | Each run rewrites the day's file with everything recorded so far today. Simple and self-healing. +| Append | Each run adds only records captured since the last successful run — no duplicates, tiny writes. (Once-daily schedules always rewrite.) Append works for CSV, JSON, Markdown, OwnTracks, Overland, and GeoJSON. GPX and KML always rewrite the full day, because valid XML files can't be naively concatenated. @@ -43,10 +43,10 @@ Append works for CSV, JSON, Markdown, OwnTracks, Overland, and GeoJSON. GPX and iOS never guarantees background execution, so Auto Export layers its chances: -- Background refresh — iOS schedules the app to wake near each run. -- A silent push — iso.me's scheduling service nudges the app at the fire time. The service only ever holds timing metadata (your time zone, the schedule, a push token) — never location records, file contents, or folder names. -- A fallback notification — if nothing ran by a minute after the scheduled time, you get a tappable “Daily Export Ready” notification; tapping runs it. -- Catch-up — opening the app runs any overdue occurrence automatically. +- Background refresh — iOS schedules the app to wake near each run. +- A silent push — iso.me's scheduling service nudges the app at the fire time. The service only ever holds timing metadata (your time zone, the schedule, a push token) — never location records, file contents, or folder names. +- A fallback notification — if nothing ran by a minute after the scheduled time, you get a tappable “Daily Export Ready” notification; tapping runs it. +- Catch-up — opening the app runs any overdue occurrence automatically. If a run fails you'll get a notification with the reason and a retry; the schedule itself keeps going. diff --git a/marketing/public/_markdown/docs/export-import/index.md b/marketing/public/_markdown/docs/export-import/index.md index 3fcbffc8..d40e73d6 100644 --- a/marketing/public/_markdown/docs/export-import/index.md +++ b/marketing/public/_markdown/docs/export-import/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 6 of 11 +§ Docs · Guide 6 of 11 # Export and restore location history @@ -24,25 +24,25 @@ Free vs Pro. Building and previewing exports is free. Writing export files (from ## Eight formats -| Format | Best for -| JSON | Structured visit and point records, scripts, and tooling. -| CSV | Spreadsheets and analysis. -| Markdown | Human-readable journals — single outings export as a front-matter page with visits and route points. -| GeoJSON | Mapping tools and GIS. -| GPX | GPS tools and route viewers; visits become waypoints, routes become tracks. -| KML | Google Earth and Earth-compatible viewers. -| OwnTracks | OwnTracks-ecosystem tools (route points). -| Overland | Overland-ecosystem tools (route points). +| Format | Best for +| JSON | Structured visit and point records, scripts, and tooling. +| CSV | Spreadsheets and analysis. +| Markdown | Human-readable journals — single outings export as a front-matter page with visits and route points. +| GeoJSON | Mapping tools and GIS. +| GPX | GPS tools and route viewers; visits become waypoints, routes become tracks. +| KML | Google Earth and Earth-compatible viewers. +| OwnTracks | OwnTracks-ecosystem tools (route points). +| Overland | Overland-ecosystem tools (route points). Choose any mix of formats in one export; each becomes its own file. OwnTracks and Overland formats carry route points (visits exports in those slots fall back to JSON). ## What gets exported -- Data: visits, route points, outings, or all of it. -- Date range: all time (default), today, yesterday, last 7 or 30 days, this month, or a custom range. -- Time of day (off by default): keep only records between two times — windows that cross midnight work too. -- Filters: only completed visits, minimum visit duration, exclude GPS glitches, and a maximum-accuracy cap (≤ 10 / 25 / 50 / 100 m). -- Fields: per-format toggles for names, addresses, durations, coordinates, notes, altitude, speed, accuracy, and glitch flags. +- Data: visits, route points, outings, or all of it. +- Date range: all time (default), today, yesterday, last 7 or 30 days, this month, or a custom range. +- Time of day (off by default): keep only records between two times — windows that cross midnight work too. +- Filters: only completed visits, minimum visit duration, exclude GPS glitches, and a maximum-accuracy cap (≤ 10 / 25 / 50 / 100 m). +- Fields: per-format toggles for names, addresses, durations, coordinates, notes, altitude, speed, accuracy, and glitch flags. Your entire setup — formats, data kind, filters, field toggles — is remembered between launches. @@ -52,15 +52,15 @@ File names come from a template you control. These tokens are available: `{date}` `{year}` `{month}` `{dayNumber}` `{weekday}` `{monthName}` `{quarter}` `{datetime}` `{time}` `{day}` `{type}` `{title}` `{name}` `{format}` -- Use `/` in a template to build dated subfolders. -- Built-in presets: Readable (default) `iso.me - {day} {date} - {type}`, Compact, and Dated `{year}/{year}-{month}/Daily Track - {date}`. -- A live preview shows the resolved path as you type. +- Use `/` in a template to build dated subfolders. +- Built-in presets: Readable (default) `iso.me - {day} {date} - {type}`, Compact, and Dated `{year}/{year}-{month}/Daily Track - {date}`. +- A live preview shows the resolved path as you type. ## Output layout -- Single file (default) or one file per day — handy for journals and incremental backups. -- Exporting outings produces one file per outing automatically. -- Collisions are auto-suffixed so nothing overwrites. +- Single file (default) or one file per day — handy for journals and incremental backups. +- Exporting outings produces one file per outing automatically. +- Collisions are auto-suffixed so nothing overwrites. ## Saving and sharing @@ -68,21 +68,21 @@ Pick a default folder (with auto-save on by default) and exports land there sile ## Import -Settings → Import file accepts visit and point files exported from iso.me as JSON, CSV, or Markdown. Importing is free. A matching file extension alone does not make another app's file compatible: Google Timeline archives are not supported. +Settings → Import file accepts visit and point files exported from iso.me as JSON, CSV, or Markdown. Importing is free. A matching file extension alone does not make another app's file compatible: The verified App Store 1.7.16 build does not support Google Timeline archives; its importer also lacks the newer preview and duplicate checks. -Choose a file for the next task -| Format | Useful for | Import into iso.me -| iso.me JSON | Structured visit or point records | Supported visit and point exports -| iso.me CSV / Markdown | Spreadsheets / readable records | Supported visit and point exports; required fields must remain -| GPX / KML / GeoJSON | Mapping tools and route viewers | No -| OwnTracks / Overland | Compatible location tools | No +Choose a file for the next task +| Format | Useful for | Import into iso.me +| iso.me JSON | Structured visit or point records | Supported visit and point exports +| iso.me CSV / Markdown | Spreadsheets / readable records | Supported visit and point exports; required fields must remain +| GPX / KML / GeoJSON | Mapping tools and route viewers | No +| OwnTracks / Overland | Compatible location tools | No ## Keep a copy and check it -- Select visits or route points, JSON, and the dates you want to retain. Export each data type you need; keep all generated files. -- Preview the result. Check that filters, field choices, and dates have not excluded required records. -- Export to a folder you control and confirm the files exist in Files before deleting or replacing anything. -- When importing later, keep the originals and inspect several dates, visits, and points after the import. Do not assume every setting, photo association, or edited outing is restored. +- Select visits or route points, JSON, and the dates you want to retain. Export each data type you need; keep all generated files. +- Preview the result. Check that filters, field choices, and dates have not excluded required records. +- Export to a folder you control and confirm the files exist in Files before deleting or replacing anything. +- When importing later, keep the originals and inspect several dates, visits, and points after the import. Do not assume every setting, photo association, or edited outing is restored. [Automatic exports](https://isome.isolated.tech/docs/automatic-exports/) can keep scheduled copies, subject to iOS background execution. For the recording workflow, see [the private location journal guide](https://isome.isolated.tech/blog/private-location-journal-iphone/). For a route file, follow [the GPX recording walkthrough](https://isome.isolated.tech/blog/record-iphone-route-gpx/). For restorable records, use [the backup and restore checklist](https://isome.isolated.tech/blog/back-up-iphone-location-history/). Comparing apps? Read [iso.me and Google Timeline](https://isome.isolated.tech/compare/google-maps-timeline/). diff --git a/marketing/public/_markdown/docs/getting-started/index.md b/marketing/public/_markdown/docs/getting-started/index.md index feebf6f9..424b4ff8 100644 --- a/marketing/public/_markdown/docs/getting-started/index.md +++ b/marketing/public/_markdown/docs/getting-started/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 1 of 11 +§ Docs · Guide 1 of 11 # Getting started @@ -26,11 +26,11 @@ iso.me is a free download on the App Store. There is no account to create and no ## The onboarding steps -- Welcome — a short overview of what iso.me records and where it keeps it. -- Core features — visit timeline, route recording, and exports at a glance. -- Permission setup — iso.me asks for While Using location access first, then offers Always. Always is what enables automatic visit detection while the app is in the background; you can decline and still use manual tracking. If permission is denied, the app links you straight to iOS Settings. -- Connect Photos (optional) — you can enable photo moments now or skip entirely. Skipping changes nothing else. -- You're all set — optionally tick Start tracking immediately and iso.me begins recording the moment onboarding finishes. +- Welcome — a short overview of what iso.me records and where it keeps it. +- Core features — visit timeline, route recording, and exports at a glance. +- Permission setup — iso.me asks for While Using location access first, then offers Always. Always is what enables automatic visit detection while the app is in the background; you can decline and still use manual tracking. If permission is denied, the app links you straight to iOS Settings. +- Connect Photos (optional) — you can enable photo moments now or skip entirely. Skipping changes nothing else. +- You're all set — optionally tick Start tracking immediately and iso.me begins recording the moment onboarding finishes. ## After onboarding @@ -38,9 +38,9 @@ You land on the Map tab. The other tabs are Timeline (your day, visit by visit), ## Your first day -- Start tracking from the map pill before a walk or drive — you'll see the path draw in, and a Live Activity appears on your lock screen. -- Stop tracking from the pill, the Live Activity's Stop button, Siri, or automatically with the auto-stop timer. -- Open the Timeline tab to review where you went, how long you stayed, and how far you moved. +- Start tracking from the map pill before a walk or drive — you'll see the path draw in, and a Live Activity appears on your lock screen. +- Stop tracking from the pill, the Live Activity's Stop button, Siri, or automatically with the auto-stop timer. +- Open the Timeline tab to review where you went, how long you stayed, and how far you moved. Where is my data? On your iPhone only. See the [Privacy & your data](https://isome.isolated.tech/docs/privacy-data) guide for the complete picture of storage, network requests, and deletion. diff --git a/marketing/public/_markdown/docs/index.md b/marketing/public/_markdown/docs/index.md index 0d28290d..a8c7bb23 100644 --- a/marketing/public/_markdown/docs/index.md +++ b/marketing/public/_markdown/docs/index.md @@ -1,4 +1,4 @@ -§ Docs · iso.me handbook +§ Docs · iso.me handbook # Documentation @@ -20,67 +20,67 @@ Questions [Email us](mailto:cody.bontecou@gmail.com) -[ Guide 01 +[ Guide 01 ## Getting started Install, onboarding, permissions, and your first tracking session. -](https://isome.isolated.tech/docs/getting-started/) [ Guide 02 +](https://isome.isolated.tech/docs/getting-started/) [ Guide 02 ## Visits, routes & battery How automatic visit detection and route recording work, and the settings that control them. -](https://isome.isolated.tech/docs/tracking/) [ Guide 03 +](https://isome.isolated.tech/docs/tracking/) [ Guide 03 ## Timeline & outings The daily timeline, inferred outings, route replay, and editing or deleting sessions. -](https://isome.isolated.tech/docs/timeline-outings/) [ Guide 04 +](https://isome.isolated.tech/docs/timeline-outings/) [ Guide 04 ## Places, corrections & manual entries Confirm or correct detected visits, save places, and add visits by hand. -](https://isome.isolated.tech/docs/places/) [ Guide 05 +](https://isome.isolated.tech/docs/places/) [ Guide 05 ## Photos on the map Optionally connect your Photos library to place pictures on your map and outings. -](https://isome.isolated.tech/docs/photos/) [ Pro 06 +](https://isome.isolated.tech/docs/photos/) [ Pro 06 ## Export and restore location history Eight export formats, filters, filename templates, and free import for restores. -](https://isome.isolated.tech/docs/export-import/) [ Pro 07 +](https://isome.isolated.tech/docs/export-import/) [ Pro 07 ## Automatic exports Schedule exports once a day or every few hours, keeping one file per day. -](https://isome.isolated.tech/docs/automatic-exports/) [ Pro 08 +](https://isome.isolated.tech/docs/automatic-exports/) [ Pro 08 ## Webhooks & self-hosting Configure optional delivery and verify your receiver’s payload and authentication requirements. -](https://isome.isolated.tech/docs/webhooks/) [ Guide 09 +](https://isome.isolated.tech/docs/webhooks/) [ Guide 09 ## Siri & Shortcuts Nine actions for tracking, stats, renaming, and exports. -](https://isome.isolated.tech/docs/siri-shortcuts/) [ Guide 10 +](https://isome.isolated.tech/docs/siri-shortcuts/) [ Guide 10 ## Record Apple Watch GPS routes without your iPhone Independent watch tracking, offline sync, and complications. -](https://isome.isolated.tech/docs/apple-watch/) [ Guide 11 +](https://isome.isolated.tech/docs/apple-watch/) [ Guide 11 ## Privacy & your data diff --git a/marketing/public/_markdown/docs/photos/index.md b/marketing/public/_markdown/docs/photos/index.md index 08eca22a..00f67635 100644 --- a/marketing/public/_markdown/docs/photos/index.md +++ b/marketing/public/_markdown/docs/photos/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 5 of 11 +§ Docs · Guide 5 of 11 # Photos on the map @@ -28,9 +28,9 @@ With photo moments enabled, iso.me can show geotagged photos from your library a Each photo is matched to a location using the first source that works: -- The photo's own GPS — geotagged photos are placed exactly where they were taken. -- Your route — otherwise iso.me looks for the nearest recorded GPS point within about 15 minutes of the capture time. -- A visit — otherwise, if the capture time falls inside a visit (with a little grace), the photo attaches to that place. +- The photo's own GPS — geotagged photos are placed exactly where they were taken. +- Your route — otherwise iso.me looks for the nearest recorded GPS point within about 15 minutes of the capture time. +- A visit — otherwise, if the capture time falls inside a visit (with a little grace), the photo attaches to that place. Photos that match none of these are simply skipped. @@ -40,10 +40,10 @@ Photo files never leave your Photos library. iso.me stores only each photo's loc ## Controls -- Automatic syncing (off by default) re-scans your library in the background, at most every 10 minutes, and re-syncs whenever your library changes. -- Map markers (off by default) — enable from the map's filter bar or Settings; nearby photos group into stacked clusters with a count badge. -- Thumbnails on markers can be turned off if you prefer plain pins. -- Tap any marker for a quick view, or open it full-screen to swipe through the day's photos. +- Automatic syncing (off by default) re-scans your library in the background, at most every 10 minutes, and re-syncs whenever your library changes. +- Map markers (off by default) — enable from the map's filter bar or Settings; nearby photos group into stacked clusters with a count badge. +- Thumbnails on markers can be turned off if you prefer plain pins. +- Tap any marker for a quick view, or open it full-screen to swipe through the day's photos. If a photo disappears from your library (with full access), iso.me cleans up its record automatically. diff --git a/marketing/public/_markdown/docs/places/index.md b/marketing/public/_markdown/docs/places/index.md index 1378a999..3c52bad9 100644 --- a/marketing/public/_markdown/docs/places/index.md +++ b/marketing/public/_markdown/docs/places/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 4 of 11 +§ Docs · Guide 4 of 11 # Places, corrections & manual entries @@ -26,25 +26,25 @@ Every visit carries a status: unconfirmed (as detected), confirmed (you approved ## Confirming and correcting -- Tap a visit on the map or in the timeline to open its detail sheet, then Confirm place to accept the detected name. -- To fix a wrong name, edit it or pick from nearby business suggestions — real places found via Apple Maps around the visit's location, searchable in the sheet. -- Undo correction restores the originally detected name, address, and position. -- Arrival and departure times are editable (with a “still here” toggle for ongoing visits), and notes can be attached to any visit. +- Tap a visit on the map or in the timeline to open its detail sheet, then Confirm place to accept the detected name. +- To fix a wrong name, edit it or pick from nearby business suggestions — real places found via Apple Maps around the visit's location, searchable in the sheet. +- Undo correction restores the originally detected name, address, and position. +- Arrival and departure times are editable (with a “still here” toggle for ongoing visits), and notes can be attached to any visit. ## Saved places Confirming or correcting a visit also saves the place — a name, position, and a match radius (default 150 m). From then on, any new visit inside that radius is automatically named from the saved place and marked confirmed. No more re-correcting “Home” every week. -- Saved places are manageable from the manual-entry sheet: select, swipe to delete, or create new ones with a radius of 50 / 100 / 150 / 250 m. -- Places with the same name at nearly the same spot update each other instead of piling up. +- Saved places are manageable from the manual-entry sheet: select, swipe to delete, or create new ones with a radius of 50 / 100 / 150 / 250 m. +- Places with the same name at nearly the same spot update each other instead of piling up. ## Manual and past visits The + menu on the map offers three ways to add history by hand: -- Save current place — names where you are right now. -- Add past visit — pick a place, an arrival, and a departure; the map then jumps to that day so you can see it in context. -- Add place manually — search Apple Maps, drop a pin, pick a saved place, or use your current location; optionally save it as a reusable place. +- Save current place — names where you are right now. +- Add past visit — pick a place, an arrival, and a departure; the map then jumps to that day so you can see it in context. +- Add place manually — search Apple Maps, drop a pin, pick a saved place, or use your current location; optionally save it as a reusable place. Locations can be chosen by searching Apple Maps, dropping a pin on a map, reusing a saved place, or using your current GPS position. Past visits require a departure time and never silently fall back to “here”. diff --git a/marketing/public/_markdown/docs/privacy-data/index.md b/marketing/public/_markdown/docs/privacy-data/index.md index 322c00e2..5d23d368 100644 --- a/marketing/public/_markdown/docs/privacy-data/index.md +++ b/marketing/public/_markdown/docs/privacy-data/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 11 of 11 +§ Docs · Guide 11 of 11 # Privacy & your data @@ -26,12 +26,12 @@ Your location history — visits, routes, outings, saved places, photo matches ## Everything that can leave your device -| Where | What's sent | When | Off switch -| Apple geocoding | Coordinates of a visit (to fetch its name/address) | When naming visits | Settings → Location names -| Apple Maps | Search terms / route segment endpoints (place search, suggestions, road-matched lines, lock-screen map images) | When you use those features | Features are opt-in per use; road-matching toggle in map filters -| iso.me analytics (first-party, on by default) | Which onboarding steps were viewed, permission choices, purchase outcomes, app version, and a random install ID — never coordinates, visits, routes, or anything you type | During onboarding and purchases | None in-app today; deleting the app removes the install ID -| Export scheduler | Time zone, schedule times, push token, random install ID — timing metadata only, no location or file contents | Only if you enable Auto Export | Turn Auto Export off -| Your webhook | Location points and visits, in your chosen format | Only after you configure an endpoint | Disable webhooks (off by default) +| Where | What's sent | When | Off switch +| Apple geocoding | Coordinates of a visit (to fetch its name/address) | When naming visits | Settings → Location names +| Apple Maps | Search terms / route segment endpoints (place search, suggestions, road-matched lines, lock-screen map images) | When you use those features | Features are opt-in per use; road-matching toggle in map filters +| iso.me analytics (first-party, on by default) | Which onboarding steps were viewed, permission choices, purchase outcomes, app version, and a random install ID — never coordinates, visits, routes, or anything you type | During onboarding and purchases | None in-app today; deleting the app removes the install ID +| Export scheduler | Time zone, schedule times, push token, random install ID — timing metadata only, no location or file contents | Only if you enable Auto Export | Turn Auto Export off +| Your webhook | Location points and visits, in your chosen format | Only after you configure an endpoint | Disable webhooks (off by default) ## Photos @@ -39,9 +39,9 @@ The photo feature reads your library on-device to match pictures to places. Phot ## Deleting your data -- Everything, in-app: Settings → Data → Clear all data permanently removes every visit, point, outing, photo match, and saved place. -- Everything, bluntly: deleting the app removes your entire journal and the local analytics install ID from that device. -- Single items: delete any visit or outing from its detail page. +- Everything, in-app: Settings → Data → Clear all data permanently removes every visit, point, outing, photo match, and saved place. +- Everything, bluntly: deleting the app removes your entire journal and the local analytics install ID from that device. +- Single items: delete any visit or outing from its detail page. ## Backups are your job (by design) @@ -49,10 +49,10 @@ Because nothing is synced to a cloud, there is no server copy to fall back on. E ## Permissions iso.me requests -| Permission | Why -| Location — Always | Automatic visit detection in the background (While-Using still works for manual sessions). -| Photos (optional) | Matching your pictures to places; never modifies your library. -| Notifications (optional) | Auto Export status and retry notices. +| Permission | Why +| Location — Always | Automatic visit detection in the background (While-Using still works for manual sessions). +| Photos (optional) | Matching your pictures to places; never modifies your library. +| Notifications (optional) | Auto Export status and retry notices. [← PreviousRecord Apple Watch GPS routes without your iPhone](https://isome.isolated.tech/docs/apple-watch/) diff --git a/marketing/public/_markdown/docs/siri-shortcuts/index.md b/marketing/public/_markdown/docs/siri-shortcuts/index.md index 5e2090cc..f470d561 100644 --- a/marketing/public/_markdown/docs/siri-shortcuts/index.md +++ b/marketing/public/_markdown/docs/siri-shortcuts/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 9 of 11 +§ Docs · Guide 9 of 11 # Siri & Shortcuts @@ -24,23 +24,23 @@ Back to Every action runs without opening the app. Find them in the Shortcuts app under iso.me, or just talk to Siri. -| Action | What it does | Siri phrase example -| Start Tracking | Begins a recording session. | “Start iso.me” -| Stop Tracking | Ends the session — even if the app isn't running. | “Stop tracking with iso.me” -| Rename Current Outing | Sets the active outing's name (parameter: name). | “Name my iso.me outing” -| Today's Distance | Returns how far you've moved today. | “How far have I gone with iso.me?” -| Today's Tracking Duration | Returns how long the session has run. | “iso.me tracking duration” -| Today's Visits | Returns today's visit count. | “How many visits today in iso.me?” -| Export Today's Data | Produces a file of today's visits and route (parameter: format, default JSON). | “Export today's data from iso.me” -| Export Today's Outings | Same, for outings. | “Export today's iso.me outings” -| Export Yesterday's Data | Yesterday's visits and route as a file. | “Export yesterday's iso.me tracks” +| Action | What it does | Siri phrase example +| Start Tracking | Begins a recording session. | “Start iso.me” +| Stop Tracking | Ends the session — even if the app isn't running. | “Stop tracking with iso.me” +| Rename Current Outing | Sets the active outing's name (parameter: name). | “Name my iso.me outing” +| Today's Distance | Returns how far you've moved today. | “How far have I gone with iso.me?” +| Today's Tracking Duration | Returns how long the session has run. | “iso.me tracking duration” +| Today's Visits | Returns today's visit count. | “How many visits today in iso.me?” +| Export Today's Data | Produces a file of today's visits and route (parameter: format, default JSON). | “Export today's data from iso.me” +| Export Today's Outings | Same, for outings. | “Export today's iso.me outings” +| Export Yesterday's Data | Yesterday's visits and route as a file. | “Export yesterday's iso.me tracks” ## Automation ideas -- Bind Start Tracking to the Action Button for one-press recording. -- An automation that runs Export Today's Data every evening and hands the file to another shortcut — your own export pipeline. -- Ask Siri for Today's Visits or Distance as a daily digest. -- Rename an outing mid-hike: “Name my iso.me outing Ridge Trail.” +- Bind Start Tracking to the Action Button for one-press recording. +- An automation that runs Export Today's Data every evening and hands the file to another shortcut — your own export pipeline. +- Ask Siri for Today's Visits or Distance as a daily digest. +- Rename an outing mid-hike: “Name my iso.me outing Ridge Trail.” Export actions produce a file in your chosen format that Shortcuts can save, message, or pass to other apps. diff --git a/marketing/public/_markdown/docs/timeline-outings/index.md b/marketing/public/_markdown/docs/timeline-outings/index.md index 87e3f381..ed183f15 100644 --- a/marketing/public/_markdown/docs/timeline-outings/index.md +++ b/marketing/public/_markdown/docs/timeline-outings/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 3 of 11 +§ Docs · Guide 3 of 11 # Timeline & outings @@ -30,19 +30,19 @@ A movement session (outing) is recorded when you pressed Start, and inferred whe Inference is configurable in Settings → Inferred outings: -| Setting | Options | Default -| Auto-generate | On / Off | On -| Split after (quiet gap) | 15 m / 30 m / 1 h / 2 h / 4 h | 30 minutes -| Ignore shorter than | None / 5 m / 15 m / 30 m / 1 h | None -| Minimum GPS points | 1 / 2 / 3 / 5 / 10 | 1 +| Setting | Options | Default +| Auto-generate | On / Off | On +| Split after (quiet gap) | 15 m / 30 m / 1 h / 2 h / 4 h | 30 minutes +| Ignore shorter than | None / 5 m / 15 m / 30 m / 1 h | None +| Minimum GPS points | 1 / 2 / 3 / 5 / 10 | 1 ## Outing detail Tap any outing for its full record: a road-matched mini map, start and end times, duration, distance, point count, GPS-glitch count, and average speed. Recorded outings can be renamed and given notes (inferred ones can't — edit the points' day instead). Linked visits and photos appear below. -- Show on map focuses the Map tab on this outing's path. -- Export saves this single outing in your choice of format (a Pro feature; the picker remembers your format). -- Delete outing removes the session and its GPS points — visits are kept. Deleting the active outing stops tracking first. +- Show on map focuses the Map tab on this outing's path. +- Export saves this single outing in your choice of format (a Pro feature; the picker remembers your format). +- Delete outing removes the session and its GPS points — visits are kept. Deleting the active outing stops tracking first. ## Route replay @@ -54,6 +54,12 @@ Outing lists can be sorted by newest, oldest, longest duration, distance, or poi If a recorded day looks incomplete, follow the [missing visits and route points checklist](https://isome.isolated.tech/blog/missing-location-history-iphone/) before deleting records or retrying an import. +## Country Days + +Timeline → Country Days counts local dates represented by visits, route points, and manual stays. Review this year, the last 365 days, or all time. A travel date can count in more than one country; gaps are not filled automatically. Viewing and manual stays are free; writing the country-date CSV uses the export purchase. + +See [how to track days spent in each country](https://isome.isolated.tech/blog/track-days-in-country-iphone/) for timezone, network-geocoding, and counting details. + [← PreviousVisits, routes & battery](https://isome.isolated.tech/docs/tracking/) [Next →Places, corrections & manual entries](https://isome.isolated.tech/docs/places/) Source: https://isome.isolated.tech/docs/timeline-outings/ diff --git a/marketing/public/_markdown/docs/tracking/index.md b/marketing/public/_markdown/docs/tracking/index.md index a6b47c5c..e3acfff7 100644 --- a/marketing/public/_markdown/docs/tracking/index.md +++ b/marketing/public/_markdown/docs/tracking/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 2 of 11 +§ Docs · Guide 2 of 11 # Visits, routes & battery @@ -26,10 +26,10 @@ iso.me records visits (arrivals and departures) and routes (GPS paths). Start en ## Starting and stopping -- Map pill — the floating control on the Map tab shows live duration and distance while recording. -- Live Activity — lock screen and Dynamic Island show progress and include a Stop button. -- Siri / Shortcuts — “Start iso.me” and “Stop tracking with iso.me” phrases work hands-free. -- Auto-stop timer — optional safety net that ends tracking automatically. +- Map pill — the floating control on the Map tab shows live duration and distance while recording. +- Live Activity — lock screen and Dynamic Island show progress and include a Stop button. +- Siri / Shortcuts — “Start iso.me” and “Stop tracking with iso.me” phrases work hands-free. +- Auto-stop timer — optional safety net that ends tracking automatically. For a walkthrough, see [how to keep a private location journal](https://isome.isolated.tech/blog/private-location-journal-iphone/) or [record an iPhone route and export GPX](https://isome.isolated.tech/blog/record-iphone-route-gpx/). @@ -43,17 +43,17 @@ New visits are reverse-geocoded to a name and address automatically, unless you' ## Route recording quality -- Only fixes with reported accuracy of 100 m or better are saved; wilder fixes are dropped. -- Obvious glitches — impossible jumps and out-and-back spikes — are flagged as GPS glitches and excluded from distances and maps by default. Enable Settings → Map display → Show GPS glitches to see them. +- Only fixes with reported accuracy of 100 m or better are saved; wilder fixes are dropped. +- Obvious glitches — impossible jumps and out-and-back spikes — are flagged as GPS glitches and excluded from distances and maps by default. Enable Settings → Map display → Show GPS glitches to see them. ## Tracking settings reference -| Setting | Options | Default | What it does -| Distance filter | 5 / 10 / 25 / 50 / 100 / 200 m | 5 m | Movement threshold requested for location updates. Larger values may reduce point density and detail; high-accuracy GPS remains active. -| Stop after | Never / 1 / 2 / 4 / 8 / 12 h | Never | Automatically ends tracking after this long, so a forgotten session can't run all day. -| Location names | On / Off | On | Whether coordinates are sent to Apple's geocoding service to name visits. -| Live Activity | On / Off | On | Lock screen / Dynamic Island status while tracking. -| Units | Metric / US | Metric | Applies everywhere: app, widgets, Live Activity, watch. +| Setting | Options | Default | What it does +| Distance filter | 5 / 10 / 25 / 50 / 100 / 200 m | 5 m | Movement threshold requested for location updates. Larger values may reduce point density and detail; high-accuracy GPS remains active. +| Stop after | Never / 1 / 2 / 4 / 8 / 12 h | Never | Automatically ends tracking after this long, so a forgotten session can't run all day. +| Location names | On / Off | On | Whether coordinates are sent to Apple's geocoding service to name visits. +| Live Activity | On / Off | On | Lock screen / Dynamic Island status while tracking. +| Units | Metric / US | Metric | Applies everywhere: app, widgets, Live Activity, watch. Battery. Tracking includes detailed GPS as well as visit monitoring, so it uses battery for as long as recording stays on. Stop when you finish, consider a 25–50 m distance filter, and set an auto-stop timer. Check the resulting route before relying on a larger filter; no battery duration is guaranteed. Follow the [battery-use comparison checklist](https://isome.isolated.tech/blog/iphone-location-tracking-battery/) to check the tradeoff on your own phone. diff --git a/marketing/public/_markdown/docs/webhooks/index.md b/marketing/public/_markdown/docs/webhooks/index.md index 0182eda0..dfedea0b 100644 --- a/marketing/public/_markdown/docs/webhooks/index.md +++ b/marketing/public/_markdown/docs/webhooks/index.md @@ -1,4 +1,4 @@ -§ Docs · Guide 8 of 11 +§ Docs · Guide 8 of 11 # Webhooks & self-hosting @@ -26,26 +26,26 @@ Pro feature, off by default. Webhooks can send your location data off your devic Webhooks deliver records to a receiver you choose, but the payload must match that receiver's API. An endpoint accepting HTTP POST is not enough to establish compatibility. Verify a dedicated test destination before enabling delivery of your history. -| Service | Endpoint shape | Format -| Dawarich batch receiver | `…/api/v1/overland/batches` | Overland; verify against your instance before use -| OwnTracks receiver | per your installation | Verify it accepts arrays of location messages -| Other receiver | its documented HTTPS endpoint | Use its required schema and authentication +| Service | Endpoint shape | Format +| Dawarich batch receiver | `…/api/v1/overland/batches` | Overland; verify against your instance before use +| OwnTracks receiver | per your installation | Verify it accepts arrays of location messages +| Other receiver | its documented HTTPS endpoint | Use its required schema and authentication iso.me encodes OwnTracks points as an array, including a single point. Dawarich's current OwnTracks receiver expects individual point fields, so do not assume those two shapes are interchangeable. Its Overland batch receiver is a different protocol. Check [Dawarich's receiver documentation](https://dawarich.app/docs/getting-started/track-your-location/) and confirm actual imported points; a completed iso.me-to-Dawarich walkthrough is not yet verified here. ## Configuration -- Endpoint — the URL to POST to. -- Format — JSON, CSV, Markdown, GeoJSON, GPX, KML, OwnTracks, or Overland. -- Authentication — none, API key in the query string, Bearer token, Basic auth, or a custom header. Credentials live in the iOS Keychain, never in plain preferences, and error messages mask them. +- Endpoint — the URL to POST to. +- Format — JSON, CSV, Markdown, GeoJSON, GPX, KML, OwnTracks, or Overland. +- Authentication — none, API key in the query string, Bearer token, Basic auth, or a custom header. Credentials live in the iOS Keychain, never in plain preferences, and error messages mask them. ## Send modes -| Mode | Behavior -| Real-time (default) | Each newly recorded point is sent as it's saved. On launch the sender “arms” itself first, so enabling webhooks never bulk-dumps your history. -| By count | Points queue and flush every 5 / 10 / 25 / 50 / 100 points. -| By time | Queued points flush every 1–60 minutes. -| Manual | Nothing sends automatically; Send now posts your entire saved history (visits and points). +| Mode | Behavior +| Real-time (default) | Each newly recorded point is sent as it's saved. On launch the sender “arms” itself first, so enabling webhooks never bulk-dumps your history. +| By count | Points queue and flush every 5 / 10 / 25 / 50 / 100 points. +| By time | Queued points flush every 1–60 minutes. +| Manual | Nothing sends automatically; Send now posts your entire saved history (visits and points). Batch modes show a live queue count with a Flush queue button. Failed sends retry automatically with backoff on network errors and server hiccups (5xx, timeouts, rate limits); authentication failures don't retry — they surface as an error. Test connection POSTs a synthetic point at latitude 0, longitude 0, with a current timestamp. A receiver can store it. A successful HTTP response confirms acceptance of that request, not that a real route was correctly imported. diff --git a/marketing/public/_markdown/index.md b/marketing/public/_markdown/index.md index fe02501e..3f16af8f 100644 --- a/marketing/public/_markdown/index.md +++ b/marketing/public/_markdown/index.md @@ -1,13 +1,13 @@ -Reviewed October 2026 · iOS & Apple Watch +Reviewed October 2026 · iOS & Apple Watch # Remember where you went. -Keep your history on your iPhone. +Keep your history on your iPhone. -Start tracking to record your own routes and detect visits, then review the day on your iPhone. No account. No iso.me location server. Recording is free; portable exports are an optional purchase. +Start tracking to record your own routes and detect visits, then review the day on your iPhone. No account. No iso.me location server. Recording is free; portable exports are an optional purchase. -[ Download free ](https://apps.apple.com/us/app/iso-me/id6761960794) [See how it works](https://isome.isolated.tech/#inside) +[ Download free ](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-home&mt=8) [See how it works](https://isome.isolated.tech/#inside) -Free download and free tracking. Lifetime export access is $19.99 Individual or $39.99 with Apple Family Sharing in the U.S. App Store; local prices reflect purchasing power. +Free download and free tracking. Lifetime export access is $19.99 Individual or $39.99 with Apple Family Sharing in the U.S. App Store; local prices reflect purchasing power. Free @@ -21,15 +21,15 @@ $19.99 / $39.99 Lifetime plans -ROUTES · 03 +ROUTES · 03 ![iso.me route detail screen](https://isome.isolated.tech/screenshots/routes-480.webp) -MAP · LIVE +MAP · LIVE ![iso.me map screen showing visits and routes](https://isome.isolated.tech/screenshots/map-480.webp) -EXPORT · 04 +EXPORT · 04 ![iso.me export screen](https://isome.isolated.tech/screenshots/export-480.webp) @@ -41,14 +41,14 @@ Visit saved locally Export when needed -Private location journal Google Timeline alternative No accounts No iso.me location servers Daily timeline & outings Eight export formats Independent Apple Watch tracking Optional Apple geocoding Scheduled auto-exports Private location journal Google Timeline alternative No accounts No iso.me location servers Daily timeline & outings Eight export formats Independent Apple Watch tracking Optional Apple geocoding Scheduled auto-exports +Private location journal Google Timeline alternative No accounts No iso.me location servers Daily timeline & outings Eight export formats Independent Apple Watch tracking Optional Apple geocoding Scheduled auto-exports Private location journal Google Timeline alternative No accounts No iso.me location servers Daily timeline & outings Eight export formats Independent Apple Watch tracking Optional Apple geocoding Scheduled auto-exports -§ 01 What you get +§ 01 What you get ## A location history you can actually trust. Newly launched -Actively maintained +Actively maintained 01 @@ -162,13 +162,29 @@ Keep separate visits and points, verify the saved files, and restore supported r Use Apple Watch GPS recording and transfer the queued points to your phone when it reconnects. -§ 02 Why people install it +07 + +### [Track days spent in each country](https://isome.isolated.tech/blog/track-days-in-country-iphone/) + +Review local dates, account for travel days, and add a manual stay when a trip was not recorded. + +Reading on your computer? Scan this code with your iPhone camera to open iso.me in the App Store. + +[ + +![QR code linking to iso.me on the App Store](https://isome.isolated.tech/assets/app-store-qr.png) + +](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-home&mt=8) + +[Open the App Store link](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-home&mt=8). Recording is free; file exports are optional purchases. + +§ 02 Why people install it ## For the moments you want to remember, not share. Trips Archives -Personal timeline +Personal timeline Trips @@ -194,94 +210,94 @@ Alternative Record visits and routes without a Google account. [Compare storage, backups, exports, and tradeoffs](https://isome.isolated.tech/compare/google-maps-timeline/). -§ 03 Inside the app +§ 03 Inside the app ## Built like an instrument, not a feed. Tactile UI -Local-first workflow +Local-first workflow -▌ MAP · 01 +▌ MAP · 01 ### Visits and routes, drawn together. The map view gives you one calm picture of your significant places and recorded paths. It is built for recall: where you stopped, how long you stayed, and how you moved between places. -- Place markers for meaningful stops -- Route lines for intentional recordings -- A private map that stays on your device +- Place markers for meaningful stops +- Route lines for intentional recordings +- A private map that stays on your device -MAP · 01 +MAP · 01 ![iso.me map screen](https://isome.isolated.tech/screenshots/map-480.webp) -▌ ROUTES · 02 +▌ ROUTES · 02 ### Save the path, not just the pin. For walks, hikes, bike rides, road trips, and site visits, routes help preserve the shape of the day instead of reducing it to a single dot. -- High-accuracy sessions for detailed paths -- Distance and duration context -- Useful for travel logs and personal archives +- High-accuracy sessions for detailed paths +- Distance and duration context +- Useful for travel logs and personal archives -ROUTES · 02 +ROUTES · 02 ![iso.me routes screen showing recorded path details](https://isome.isolated.tech/screenshots/routes-480.webp) -▌ EXPORT · 03 +▌ EXPORT · 03 ### Take your history with you. Your location journal should not be trapped in an app. Export visits, route points, or both, then keep a backup, analyze it privately, or turn it into a written travel log. -- Eight formats, from JSON and CSV to GPX and OwnTracks -- Filters for dates, times, fields, and accuracy -- Per-day files, name templates, and scheduled runs -- Free import for restoring an export +- Eight formats, from JSON and CSV to GPX and OwnTracks +- Filters for dates, times, fields, and accuracy +- Per-day files, name templates, and scheduled runs +- Free import for restoring an export -EXPORT · 03 +EXPORT · 03 ![iso.me export screen with JSON CSV and Markdown options](https://isome.isolated.tech/screenshots/export-480.webp) -▌ SETTINGS · 04 +▌ SETTINGS · 04 ### Control the tradeoffs. Location apps should be explicit about power and privacy. iso.me puts recording, distance filtering, place naming, and auto-stop controls in one place. Check them before starting a session. -- GPS recording with a distance filter -- Per-session auto-shutoff options -- Optional Apple geocoding for readable names +- GPS recording with a distance filter +- Per-session auto-shutoff options +- Optional Apple geocoding for readable names -SETTINGS · 04 +SETTINGS · 04 ![iso.me settings screen with tracking controls](https://isome.isolated.tech/screenshots/settings-480.webp) -On-device by design +On-device by design ## Your location history is not a growth dataset. -Your recorded visits and routes live on your iPhone, with no iso.me account or server archive of that history. Apple services provide place names and map features. First-party onboarding telemetry is on by default; optional exports and webhooks send data only where you choose. [Read the network and storage details](https://isome.isolated.tech/privacy). +Your recorded visits and routes live on your iPhone, with no iso.me account or server archive of that history. Apple services provide place names and map features. First-party onboarding telemetry is on by default; optional exports and webhooks send data only where you choose. [Read the network and storage details](https://isome.isolated.tech/privacy). -iso.me location uploads None +iso.me location uploads None -Account required No +Account required No -Onboarding telemetry On by default +Onboarding telemetry On by default -Apple geocoding Optional +Apple geocoding Optional -Local storage On device +Local storage On device -Export ownership Yours +Export ownership Yours -§ 03 Everything in the box +§ 03 Everything in the box ## The full capability ledger. Included · Free -Pro · One-time unlock +Pro · One-time unlock Daily timeline & outingsIncluded @@ -311,109 +327,109 @@ Scheduled auto-exports — daily or 1–23 hPro Webhooks — OwnTracks · Overland formatsPro -§ 04 Trust and support +§ 04 Trust and support ## Built by Cody Bontecou at isolated.tech. -iso.me is an independent app, not a data broker product. The site makes no fabricated ratings claims; the honest proof is simpler: a current App Store listing, visible support, a privacy policy that spells out every network request the app can make, and an export path for your data. +iso.me is an independent app, not a data broker product. The site makes no fabricated ratings claims; the honest proof is simpler: a current App Store listing, visible support, a privacy policy that spells out every network request the app can make, and an export path for your data. -Need help, want to report a bug, or have a question before installing? Email [cody.bontecou@gmail.com](mailto:cody.bontecou@gmail.com). +Need help, want to report a bug, or have a question before installing? Email [cody.bontecou@gmail.com](mailto:cody.bontecou@gmail.com). -Creator Cody / isolated.tech +Creator Cody / isolated.tech -Freshness Reviewed October 2026 +Freshness Reviewed October 2026 -Ratings claim Not fabricated +Ratings claim Not fabricated -Support Email available +Support Email available -§ 05 Pricing +§ 05 Pricing ## Free tracking. Pay once if you need export. No subscription -No ad business +No ad business ## Install it first. Unlock export only when it matters. -iso.me is free to download, and private visit and route tracking is free. Lifetime export access covers all eight formats, scheduled auto-exports, and webhook delivery. Choose Individual for $19.99 or Family Sharing for $39.99 in the U.S. App Store; Individual owners can upgrade later for $19.99. Local prices reflect purchasing power and applicable taxes. +iso.me is free to download, and private visit and route tracking is free. Lifetime export access covers all eight formats, scheduled auto-exports, and webhook delivery. Choose Individual for $19.99 or Family Sharing for $39.99 in the U.S. App Store; Individual owners can upgrade later for $19.99. Local prices reflect purchasing power and applicable taxes. -- No subscription required for tracking -- No ads or ad targeting -- No server-side location storage -- No account wall before you can try it +- No subscription required for tracking +- No ads or ad targeting +- No server-side location storage +- No account wall before you can try it -ISO.ME PRO ● Optional unlock +ISO.ME PRO ● Optional unlock $19.99 Individual Lifetime. Family Lifetime is $39.99, and the later Family Upgrade is $19.99. One-time U.S. prices; regional pricing may vary. -- Download the appFree -- Tracking, timeline & outingsFree -- Apple Watch, widgets, ShortcutsFree -- Import from backupFree -- Export — all eight formatsPro -- Scheduled auto-exportsPro -- Webhook deliveryPro -- Individual Lifetime$19.99 once -- Family Lifetime$39.99 once -- Individual → Family upgrade$19.99 once -- Apple paymentsHandled by App Store +- Download the appFree +- Tracking, timeline & outingsFree +- Apple Watch, widgets, ShortcutsFree +- Import from backupFree +- Export — all eight formatsPro +- Scheduled auto-exportsPro +- Webhook deliveryPro +- Individual Lifetime$19.99 once +- Family Lifetime$39.99 once +- Individual → Family upgrade$19.99 once +- Apple paymentsHandled by App Store -[Get iso.me on the App Store](https://apps.apple.com/us/app/iso-me/id6761960794) +[Get iso.me on the App Store](https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-home&mt=8) -§ 06 FAQ +§ 06 FAQ ## Practical answers before you hand over location permission. -Location apps ask for meaningful trust. These answers keep the boundaries clear: what stays local, what Apple handles, what costs money, and how to leave with your data. +Location apps ask for meaningful trust. These answers keep the boundaries clear: what stays local, what Apple handles, what costs money, and how to leave with your data. -Will iso.me drain my battery? +Will iso.me drain my battery? iso.me uses iOS location services and gives you controls such as Start and Stop, distance filters, and auto-stop timers. High-accuracy route recording uses more battery, so use it for intentional sessions like trips, walks, hikes, or site visits. -Where is my location data stored? +Where is my location data stored? Your visits and routes are stored locally on your iPhone. iso.me does not require an account and does not store your location history on iso.me servers. -Does iso.me use Apple geocoding? +Does iso.me use Apple geocoding? It can, if you choose features that turn coordinates into readable place names or addresses. Those geocoding requests go through Apple's system service and are governed by Apple's privacy policies, not an iso.me location database. -Can I delete my location history? +Can I delete my location history? Yes. Delete data from the app settings. Since iso.me does not keep a server copy, deleting the app also removes the local data from that device unless you exported or backed it up first. -Can I export or import my history? +Can I export or import my history? Yes. Export supports JSON, CSV, Markdown, GeoJSON, GPX, KML, OwnTracks, and Overland for visits, route points, and outings. Import can restore a prior export, and importing is free. -Does iso.me work with Apple Watch? +Does iso.me work with Apple Watch? Yes — and the Watch app records independently. It keeps its own GPS session, works without your iPhone nearby, and queues routes offline until it can sync them back. Watch complications also show today's visits, distance, and tracking status. -Does iso.me sync with iCloud? +Does iso.me sync with iCloud? No. iso.me stores your journal locally and does not sync through iCloud. Export and import are the portable backup path, and the Apple Watch syncs directly with your iPhone rather than through the cloud. -What is free and what is Pro? +What is free and what is Pro? The app is free to download; tracking, the timeline, the Watch app, widgets, and import are free. Lifetime export access covers all eight formats, scheduled automatic exports, and webhook delivery. It costs $19.99 for Individual or $39.99 for Family in the U.S. App Store, with a $19.99 Family Upgrade available to Individual owners. Local prices reflect purchasing power and may vary by storefront. -Does iso.me work with OwnTracks, Overland, or Dawarich? +Does iso.me work with OwnTracks, Overland, or Dawarich? iso.me can POST records in OwnTracks or Overland formats to a configured receiver. Compatibility depends on that receiver’s payload schema and authentication. Verify the protocol before enabling delivery; the Dawarich workflow is not yet verified here. Webhooks require Pro and are off by default. [Read the receiver requirements](https://isome.isolated.tech/docs/webhooks/). -What can Siri and Shortcuts do? +What can Siri and Shortcuts do? iso.me exposes nine actions: start and stop tracking, rename the current outing, ask for today's distance, tracking duration, or visit count, and export today's or yesterday's data as a file. They work in the Shortcuts app, from Siri, and from automations such as the Action Button. -Can exports run automatically? +Can exports run automatically? Yes. Auto Export saves your day to a folder you pick, once daily or as often as every hour, keeping one consistent dated file per day. Wake-ups are best effort: background refresh plus a scheduling service that sends timing-only pushes and never sees your location. -Is iso.me a Google Timeline alternative? +Is iso.me a Google Timeline alternative? Yes. iso.me records your own visits and routes without a Google account. Google Timeline also stores history on your device and offers encrypted backup; iso.me differs in account requirements, export formats, and recording workflow. It does not import Google Timeline archives. [Read the comparison](https://isome.isolated.tech/compare/google-maps-timeline/). diff --git a/marketing/public/_markdown/privacy.md b/marketing/public/_markdown/privacy.md index 98f99f14..5fff6afe 100644 --- a/marketing/public/_markdown/privacy.md +++ b/marketing/public/_markdown/privacy.md @@ -1,4 +1,4 @@ -§ Legal · Document 01 +§ Legal · Document 01 # Privacy Policy @@ -26,9 +26,9 @@ A small set of optional or auxiliary features do communicate over the network. E The App uses your device's location services to: -- Automatically detect places you visit -- Record detailed routes when tracking is enabled -- Feed optional surfaces such as the Apple Watch app, widgets, and Live Activities +- Automatically detect places you visit +- Record detailed routes when tracking is enabled +- Feed optional surfaces such as the Apple Watch app, widgets, and Live Activities Your location history stays on your device unless you deliberately enable a feature that sends it elsewhere. The only such feature is optional webhook delivery (see Network Requests), which posts your data to a destination you configure yourself. @@ -36,11 +36,11 @@ Your location history stays on your device unless you deliberately enable a feat The App may make network requests in the following circumstances: -- Apple system services (optional): if readable place names are enabled, coordinates are sent to Apple's geocoding service. Place search, nearby-business suggestions, road-matched route lines, and lock-screen map snapshots also use Apple Maps services. These requests are handled by Apple and governed by Apple's privacy policy. -- First-party onboarding analytics (on by default): the App reports a limited allowlist of onboarding and purchase events — such as which onboarding step you viewed or whether a purchase succeeded — to iso.me's own analytics endpoint hosted on Cloudflare Workers. Each report includes a random install identifier, the app version, and coarse status such as your permission choice. Reports never include coordinates, visits, routes, addresses, place names, photos, or anything you type. Deleting the App removes the local install identifier. -- Webhook delivery (off by default, Pro): if you configure a webhook, the App posts your location points and visits, in your chosen format, directly to the endpoint you specify. Credentials are stored in the iOS Keychain; iso.me never sees your endpoint or your data. -- Scheduled export wake-ups (only if enabled, Pro): if you enable automatic exports, the App registers a random install identifier, an Apple push token, your time zone, and your schedule time with iso.me's scheduling endpoint so the App can be woken at the right moment. This service stores timing metadata only — never location records, export contents, folder names, or file names. -- App Store: purchases are handled entirely by Apple's App Store. iso.me does not process or store payment information. +- Apple system services (optional): if readable place names are enabled, coordinates are sent to Apple's geocoding service. Place search, nearby-business suggestions, road-matched route lines, and lock-screen map snapshots also use Apple Maps services. These requests are handled by Apple and governed by Apple's privacy policy. +- First-party onboarding analytics (on by default): the App reports a limited allowlist of onboarding and purchase events — such as which onboarding step you viewed or whether a purchase succeeded — to iso.me's own analytics endpoint hosted on Cloudflare Workers. Each report includes a random install identifier, the app version, and coarse status such as your permission choice. Reports never include coordinates, visits, routes, addresses, place names, photos, or anything you type. Deleting the App removes the local install identifier. +- Webhook delivery (off by default, Pro): if you configure a webhook, the App posts your location points and visits, in your chosen format, directly to the endpoint you specify. Credentials are stored in the iOS Keychain; iso.me never sees your endpoint or your data. +- Scheduled export wake-ups (only if enabled, Pro): if you enable automatic exports, the App registers a random install identifier, an Apple push token, your time zone, and your schedule time with iso.me's scheduling endpoint so the App can be woken at the right moment. This service stores timing metadata only — never location records, export contents, folder names, or file names. +- App Store: purchases are handled entirely by Apple's App Store. iso.me does not process or store payment information. ## Data Export @@ -48,13 +48,13 @@ You can export visits, route points, and outings at any time as JSON, CSV, Markd ## Analytics and Tracking -iso.me contains no third-party analytics SDKs, no advertising frameworks, and no trackers from other companies. The only telemetry is the first-party onboarding analytics described under Network Requests: a short allowlist of funnel events with a random install identifier and no location content. This website (not the App) additionally uses Cloudflare Web Analytics, which does not use cookies and does not track you across other sites. +iso.me contains no third-party analytics SDKs, no advertising frameworks, and no trackers from other companies. The only telemetry is the first-party onboarding analytics described under Network Requests: a short allowlist of funnel events with a random install identifier and no location content. This website (not the App) additionally uses Cloudflare Web Analytics, which does not use cookies and does not track you across other sites. After the existing analytics exclusion check allows measurement, the website also counts page loads and App Store link activations by public page, link placement, UTC day, and a coarse referrer category (search, internal, other, or direct). These counters use no cookies, browser storage, visitor identifiers, raw referrer URLs, query strings, or location files. They measure activations, not unique visitors, installs, or purchases. This collection is disabled when the browser sends Global Privacy Control or Do Not Track. Cloudflare hosts the aggregate counters. On selected acquisition pages, App Store download links also include a public campaign label and developer provider token so Apple can report campaign downloads and purchases subject to its reporting rules. These labels contain no personal information or location records. ## Third-Party Services -- Apple: geocoding, Maps search and directions, map snapshots, push notifications, and App Store purchases are Apple system services governed by Apple's privacy policy. -- Cloudflare: hosts iso.me's own analytics ingest and export-scheduling endpoints (as described above), plus this website. Cloudflare processes data as our infrastructure provider. -- Destinations you choose: webhook delivery and file exports go only to endpoints and folders you configure yourself. +- Apple: geocoding, Maps search and directions, map snapshots, push notifications, and App Store purchases are Apple system services governed by Apple's privacy policy. +- Cloudflare: hosts iso.me's own analytics ingest and export-scheduling endpoints (as described above), plus this website. Cloudflare processes data as our infrastructure provider. +- Destinations you choose: webhook delivery and file exports go only to endpoints and folders you configure yourself. ## Data Deletion diff --git a/marketing/public/_markdown/terms.md b/marketing/public/_markdown/terms.md index 8dfecb38..2c7ec287 100644 --- a/marketing/public/_markdown/terms.md +++ b/marketing/public/_markdown/terms.md @@ -1,4 +1,4 @@ -§ Legal · Document 02 +§ Legal · Document 02 # Terms of Service @@ -36,10 +36,10 @@ iso.me offers one-time Individual Lifetime and Family Lifetime in-app purchases You agree to use iso.me only for lawful purposes. You may not: -- Use the App to track any person without their knowledge and consent -- Reverse-engineer, decompile, or disassemble the App -- Redistribute or resell the App or any part of it -- Use the App in any way that violates applicable laws or regulations +- Use the App to track any person without their knowledge and consent +- Reverse-engineer, decompile, or disassemble the App +- Redistribute or resell the App or any part of it +- Use the App in any way that violates applicable laws or regulations ## 06 — Location Services diff --git a/marketing/public/_worker.js b/marketing/public/_worker.js index 8729c53f..49e46fc7 100644 --- a/marketing/public/_worker.js +++ b/marketing/public/_worker.js @@ -8,6 +8,7 @@ const pages = { "/blog/missing-location-history-iphone/": "/_markdown/blog/missing-location-history-iphone/index.md", "/blog/private-location-journal-iphone/": "/_markdown/blog/private-location-journal-iphone/index.md", "/blog/record-iphone-route-gpx/": "/_markdown/blog/record-iphone-route-gpx/index.md", + "/blog/track-days-in-country-iphone/": "/_markdown/blog/track-days-in-country-iphone/index.md", "/blog/view-location-history-iphone/": "/_markdown/blog/view-location-history-iphone/index.md", "/compare/google-maps-timeline/": "/_markdown/compare/google-maps-timeline/index.md", "/compare/": "/_markdown/compare/index.md", @@ -29,6 +30,50 @@ const pages = { "/terms": "/_markdown/terms.md" }; +async function acquisition(request, env) { + const headers = { 'Cache-Control': 'no-store' }; + const reply = (message, status) => new Response(message, { status, headers }); + if (request.method !== 'POST') return new Response(null, { status: 405, headers: { ...headers, Allow: 'POST' } }); + const url = new URL(request.url); + // Reject cross-origin/form submissions. Preview deployments don't collect counts. + if (request.headers.get('Origin') !== url.origin || + !(url.hostname === 'isome.isolated.tech' || ['127.0.0.1', 'localhost'].includes(url.hostname))) return reply('Forbidden', 403); + if (request.headers.get('Content-Type')?.split(';')[0].trim() !== 'application/json') return reply('JSON required', 415); + if (request.headers.get('Sec-GPC') === '1' || request.headers.get('DNT') === '1') return reply(null, 204); + if (!env.SEO_DB) return reply('Measurement unavailable', 503); + if (Number(request.headers.get('Content-Length')) > 512) return reply('Payload too large', 413); + let size = 0; + const chunks = []; + const reader = request.body?.getReader(); + if (!reader) return reply('Invalid event', 400); + while (true) { + const { done, value } = await reader.read(); + if (done) break; + size += value.byteLength; + if (size > 512) { await reader.cancel(); return reply('Payload too large', 413); } + chunks.push(value); + } + let event; + try { + const bytes = new Uint8Array(size); + let offset = 0; + for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.byteLength; } + event = JSON.parse(new TextDecoder().decode(bytes)); + } catch { return reply('Invalid event', 400); } + if (!event || Array.isArray(event) || Object.keys(event).sort().join(',') !== 'event,page,placement,source' || + !['page_view', 'app_store_clicked'].includes(event.event) || + !Object.hasOwn(pages, event.page) || + !['page', 'header', 'inline', 'footer', 'qr'].includes(event.placement) || + !['direct', 'internal', 'search', 'other'].includes(event.source) || + (event.event === 'page_view') !== (event.placement === 'page')) return reply('Invalid event', 400); + try { + await env.SEO_DB.prepare(`INSERT INTO website_acquisition_daily (day,event,page,placement,source,count) + VALUES (date('now'),?,?,?,?,1) ON CONFLICT(day,event,page,placement,source) + DO UPDATE SET count=count+1`).bind(event.event, event.page, event.placement, event.source).run(); + } catch { return reply('Measurement unavailable', 503); } + return reply(null, 204); +} + function quality(accept, type) { for (const entry of accept.toLowerCase().split(',')) { const [media, ...parameters] = entry.trim().split(';'); @@ -43,6 +88,7 @@ function quality(accept, type) { export default { async fetch(request, env) { const url = new URL(request.url); + if (url.pathname === '/api/v1/acquisition') return acquisition(request, env); if (request.method !== 'GET' && request.method !== 'HEAD') { return new Response(JSON.stringify({ type: 'about:blank', title: 'Method not allowed', status: 405, diff --git a/marketing/public/about.html b/marketing/public/about.html index fffb87a7..470c625e 100644 --- a/marketing/public/about.html +++ b/marketing/public/about.html @@ -188,5 +188,6 @@ })(); + diff --git a/marketing/public/api/v1/product.json b/marketing/public/api/v1/product.json index 12ea4040..8bce1f62 100644 --- a/marketing/public/api/v1/product.json +++ b/marketing/public/api/v1/product.json @@ -14,7 +14,8 @@ "Timeline and outings", "Independent Apple Watch recording", "Portable export", - "Supported import", + "Supported iso.me file import (App Store 1.7.16)", + "Country Days and manual stays", "Siri and Shortcuts", "Optional outbound webhooks" ], diff --git a/marketing/public/assets/acquisition.js b/marketing/public/assets/acquisition.js new file mode 100644 index 00000000..031f0381 --- /dev/null +++ b/marketing/public/assets/acquisition.js @@ -0,0 +1,38 @@ +/* Coarse website counts only. No cookies, storage, visitor IDs, or journal data. */ +(() => { + if (location.hostname !== 'isome.isolated.tech' || navigator.globalPrivacyControl || navigator.doNotTrack === '1') return; + let enabled = false; + let source = 'direct'; + try { + const referrer = new URL(document.referrer); + source = referrer.hostname === location.hostname ? 'internal' : + /(^|\.)(google\.[a-z.]+|bing\.com|duckduckgo\.com|search\.yahoo\.com)$/.test(referrer.hostname) ? 'search' : 'other'; + } catch { /* Empty or unreadable referrer. */ } + + function count(event, placement) { + if (!enabled) return; + // Never send the query string, referrer URL, anchor label, or visitor identifier. + fetch('/api/v1/acquisition', { + method: 'POST', credentials: 'omit', keepalive: true, referrerPolicy: 'no-referrer', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ event, page: location.pathname, placement, source }), + }).catch(() => {}); + } + document.addEventListener('click', event => { + const link = event.target.closest?.('a[href]'); + if (!link) return; + let target; + try { target = new URL(link.href); } catch { return; } + if (target.hostname !== 'apps.apple.com' || !target.pathname.includes('id6761960794')) return; + const placement = link.dataset.placement || (link.closest('footer') ? 'footer' : + link.closest('nav') ? 'header' : 'inline'); + count('app_store_clicked', placement); + }); + fetch('https://img-host.costream.workers.dev/analytics-gate', { + cache: 'no-store', mode: 'cors', credentials: 'omit', referrerPolicy: 'no-referrer', + }).then(response => response.ok ? response.json() : { track: false }) + .then(gate => { + enabled = gate?.track === true; + count('page_view', 'page'); + }).catch(() => {}); // Fail closed, preserving the existing exclusion gate. +})(); diff --git a/marketing/public/assets/app-store-qr-url.txt b/marketing/public/assets/app-store-qr-url.txt new file mode 100644 index 00000000..c43b49a4 --- /dev/null +++ b/marketing/public/assets/app-store-qr-url.txt @@ -0,0 +1 @@ +https://apps.apple.com/app/apple-store/id6761960794?pt=126424970&ct=seo-home&mt=8 diff --git a/marketing/public/assets/app-store-qr.png b/marketing/public/assets/app-store-qr.png new file mode 100644 index 00000000..3fc34051 Binary files /dev/null and b/marketing/public/assets/app-store-qr.png differ diff --git a/marketing/public/blog/back-up-iphone-location-history/index.html b/marketing/public/blog/back-up-iphone-location-history/index.html index b51211f3..b5ded040 100644 --- a/marketing/public/blog/back-up-iphone-location-history/index.html +++ b/marketing/public/blog/back-up-iphone-location-history/index.html @@ -231,7 +231,7 @@

    3. Import the supported files on the destination

  • Check several dates on Map and Timeline. Look for both visits and route points, including the earliest and most recent records you expected.
  • Keep your originals until you have checked the result. An import cannot restore records that were excluded from the export.
  • -

    Import adds records; do not assume it merges an overlapping archive or skips duplicates. Import each intended file once and inspect the result before retrying. If a file fails, retain it and read the reported format or field error before editing it. A JSON archive from Google Timeline has a different structure and is not a supported iso.me restore file.

    +

    In App Store 1.7.16, import adds records without the newer preview and duplicate checks. Do not assume overlapping files are merged. Import each intended file once and inspect the result before retrying. If a file fails, retain it and read the reported format or field error before editing it. A JSON archive from Google Timeline has a different structure and is not a supported iso.me restore file.

    Restore Purchases is separate. It restores an eligible paid entitlement through the App Store; it does not download a copy of your location history. iso.me does not provide an account-based server archive or built-in iCloud journal sync.

    @@ -308,5 +308,6 @@

    Keep the records.
    Check the copy.

    })(); + diff --git a/marketing/public/blog/index.html b/marketing/public/blog/index.html index dc0cbc61..006b9d17 100644 --- a/marketing/public/blog/index.html +++ b/marketing/public/blog/index.html @@ -791,6 +791,7 @@

    Google Timeline alternative for iPh

    Make a restorable copy or turn your visits into a readable note.

    +
    @@ -890,5 +891,6 @@

    Record with your Apple Watch

    })(); + diff --git a/marketing/public/blog/iphone-location-journal-obsidian/index.html b/marketing/public/blog/iphone-location-journal-obsidian/index.html index 571efd77..ed6c543a 100644 --- a/marketing/public/blog/iphone-location-journal-obsidian/index.html +++ b/marketing/public/blog/iphone-location-journal-obsidian/index.html @@ -286,5 +286,6 @@

    Keep the stops readable.
    Add your own context.

    })(); + diff --git a/marketing/public/blog/iphone-location-tracking-battery/index.html b/marketing/public/blog/iphone-location-tracking-battery/index.html index b877f6eb..aa66621c 100644 --- a/marketing/public/blog/iphone-location-tracking-battery/index.html +++ b/marketing/public/blog/iphone-location-tracking-battery/index.html @@ -270,5 +270,6 @@

    Keep the route you need.
    Check where it ends. + diff --git a/marketing/public/blog/missing-location-history-iphone/index.html b/marketing/public/blog/missing-location-history-iphone/index.html index 0c2bc1f3..c5684aff 100644 --- a/marketing/public/blog/missing-location-history-iphone/index.html +++ b/marketing/public/blog/missing-location-history-iphone/index.html @@ -286,5 +286,6 @@

    Check a short route.
    Then trust a longer day.

    })(); + diff --git a/marketing/public/blog/private-location-journal-iphone/index.html b/marketing/public/blog/private-location-journal-iphone/index.html index 245f670a..81f6bf38 100644 --- a/marketing/public/blog/private-location-journal-iphone/index.html +++ b/marketing/public/blog/private-location-journal-iphone/index.html @@ -672,7 +672,7 @@ Blog Docs FAQ - Download + Download @@ -688,7 +688,7 @@

    How to keep a private location journal<

    @@ -838,13 +838,14 @@

    A simple private-journal checklist

    Verify your first recording

      -
    1. Open iso.me and finish setup. Choose While Using for manual sessions, or Always if you want automatic visits in the background. You can revisit this in iOS Settings.
    2. +
    3. Open iso.me and finish setup. Choose Always if you want GPS and visit monitoring to continue in the background; While Using limits when the app can obtain locations. You can revisit this in iOS Settings.
    4. On the Map tab, start a short route with the recording control. Stop it when you finish.
    5. Open Timeline and check the date, route, and start/end times. Automatic visits need time at a place; do not expect every brief stop to appear immediately.
    6. If the result is empty, check location permission, tracking state, and the selected day before relying on a longer recording.
    -

    Download free for iPhone

    +

    Download free for iPhone

    Tracking is free. Writing export files, scheduled exports, and webhooks require the one-time unlock; importing a prior export is free. See current pricing and the setup reference.

    +

    Record your first day free

    Capture visits and routes without turning your life into a feed

    @@ -899,6 +900,7 @@

    Export without locking your memory inside one app

    Exported files are powerful because they leave the app boundary. Store them deliberately. If you put them in cloud storage, email them, or import them into another service, that copy follows the privacy rules of the place you sent it.

    +

    For a travel summary, Country Days shows the local dates behind each country total, including manual stays for gaps.

    Keep a backup you can restore

    Export visits and route points as iso.me JSON when your goal is to import those records later. Keep each generated file. GPX and KML are useful for map viewers, but cannot be imported back into iso.me. Do not assume that a file preserves every app setting or outing edit.

      @@ -943,7 +945,7 @@

      Build habits that keep the journal useful

      Start with a local journal.

      Download iso.me, keep your working location history on your iPhone, and export when you need a portable copy.

      - Get iso.me + Get iso.me @@ -962,7 +964,7 @@

      Start with a local journal.

      Privacy Terms Support - App Store + App Store @@ -1014,5 +1016,6 @@

      Start with a local journal.

      })(); + diff --git a/marketing/public/blog/record-iphone-route-gpx/index.html b/marketing/public/blog/record-iphone-route-gpx/index.html index 7b8149e9..e72d6e40 100644 --- a/marketing/public/blog/record-iphone-route-gpx/index.html +++ b/marketing/public/blog/record-iphone-route-gpx/index.html @@ -144,7 +144,7 @@
      @@ -237,7 +237,7 @@

      Keep a separate copy for restoring your journal

      Record the route.
      Choose how to keep it.

      Try free recording and export preview. The optional purchase unlocks writing files; see current pricing.

      - Download free for iPhone + Download free for iPhone

      Reviewed October 26, 2026. Steps reflect iso.me’s recording and export controls; labels can vary by app version. For setup, read the private journal guide; for existing Apple or Google records, see how to view iPhone location history.

      @@ -294,5 +294,6 @@

      Record the route.
      Choose how to keep it.

      })(); + diff --git a/marketing/public/blog/track-days-in-country-iphone/index.html b/marketing/public/blog/track-days-in-country-iphone/index.html new file mode 100644 index 00000000..def86e0d --- /dev/null +++ b/marketing/public/blog/track-days-in-country-iphone/index.html @@ -0,0 +1,260 @@ + + + + + + Track Days Spent in Each Country on iPhone — iso.me + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +

      Practical iPhone guides

      How to track days spent in each country on iPhone

      Review country totals and the dates behind them, add missing stays, and keep a personal record without an iso.me account.

      +
      +

      Count the dates you can account for

      +

      In iso.me, open Timeline → Country Days to count local dates represented by your recorded visits, route points, and manual stays. Choose this year, the last 365 days, or all time, then open a country to review its dates. Viewing the counts and adding manual stays are free. Writing the CSV file requires the optional export purchase.

      +

      This guide covers Country Days in iso.me 1.7.16. It is a personal travel journal: its rules do not determine tax residency, immigration status, or how a visa counts a day.

      + +
      + +
      +

      1. Review the dates behind each total

      +
      1. Open Timeline, then Country Days.
      2. Select a period. The default is this year; the other choices are the last 365 days and all time.
      3. Open a country and review the individual dates. A total is only useful when you understand which dates produced it.
      4. If older locations lack countries, use the analysis controls described below. If nothing was recorded for a stay, add it manually rather than expecting GPS to recreate it.
      +

      To collect new history, start recording before your trip. Start enables detailed GPS and visit monitoring together; Stop ends both. Read the first-recording guide for permissions and recording controls.

      +
      + +
      Country Days on iPhone, with period filters, country analysis, and Add stay controls
      Country Days before any country dates have been resolved. Captured in development build 1.7.17 (47), in an iOS 26.5 simulator on October 26, 2026; this is an interface example, not a recorded trip.
      + +
      +

      2. Check the counting rules

      +
      + + + + + + + +
      Presence dates, rather than a continuous travel guarantee
      SituationHow iso.me counts it
      Many points in the same country on one dateOne day for that country, rather than one day per record.
      Two countries on a travel dayThat date can count in both countries. Adding country totals may exceed the number of distinct dates.
      A record near midnightThe resolved location’s timezone determines the local date, rather than UTC or your phone’s current timezone.
      A completed visit with a verified departureIts local date range can contribute multiple dates.
      An open visit or unverified departureOnly its arrival date is counted. Route points or manual stays can account for other dates.
      Unknown country, GPS outlier, or recording gapNo invented dates or automatic continuous stay.
      Overlapping manual and recorded presenceThe date counts once per country; the source flags can show both.
      +

      A simple border-crossing example

      +

      Imagine a recorded point in Portugal on October 1 and another in Spain later that local date. Each country gets October 1. If a manual Portugal stay also includes October 1, Portugal still gets one day. If October 2 has no usable evidence or manual stay, the app does not fill it merely because you have records before and after it.

      +

      This is an invented example of the counting rules, not a captured trip. Review gaps with the missing-records checklist before changing your journal.

      +
      + +
      +

      3. Add a stay that was not recorded

      +

      Use Add stay in Country Days. Choose the country and first and last dates, add an optional note, and save. Review the affected country’s dates afterwards. You can edit or delete a manual stay when you find a mistake.

      +

      A manual stay records your account of a trip; it does not create a GPS path. Keep tickets or other original records separately if you need them. Overlapping manual stays do not multiply the same country/date.

      +
      + +
      +

      4. Identify countries in older locations

      +

      New recordings identify countries when network geocoding is enabled. Analyze saved locations checks earlier records in batches, with stop and resume controls. It can take time for a large archive.

      +

      Country identification uses Apple geocoding and follows your network-geocoding preference. A lookup sends coordinates to Apple; turning it off changes which unresolved locations can be assigned a country. Your journal remains on your device, and iso.me does not receive an archive of it. See the privacy policy for all network boundaries.

      +

      Analysis can identify a country for an existing coordinate. It cannot recover locations that were never recorded. Use a manual stay for dates you can account for independently.

      +
      + +
      +

      5. Keep a CSV copy of your country dates

      +

      Use the export control in Country Days and save the CSV to a destination you choose. The file includes country codes, local dates, and recorded/manual source information. Viewing and editing your counts are free; writing this export requires the lifetime unlock. See current pricing.

      +

      Check a known date and a travel day in the saved file. A country-date CSV is a summary, not a backup of every visit, route point, or manual stay. Keep your underlying records using the backup checklist.

      +
      + +

      Remember the country.
      Keep the dates behind the count.

      Start a free local journal and review Country Days on your iPhone.

      Download free for iPhone
      +

      Reviewed October 26, 2026 against the source used for App Store 1.7.16 build 46, including CountryDaysView, CountryDayCalculator, and CountryDayResolver. The examples are synthetic. They do not represent a new physical travel test.

      + +
      + +
      + + + + + + + diff --git a/marketing/public/blog/view-location-history-iphone/index.html b/marketing/public/blog/view-location-history-iphone/index.html index 88c418fb..7e76155e 100644 --- a/marketing/public/blog/view-location-history-iphone/index.html +++ b/marketing/public/blog/view-location-history-iphone/index.html @@ -191,7 +191,7 @@

      Open Google Maps Timeline

    1. If history is missing, confirm which account and device you used. Check your backup and deletion settings before making changes.

    Google Timeline stores history on the device and can keep an encrypted backup. To save an independent archive, Google’s iPhone instructions use Settings → Location & Privacy → Export Timeline data, then Save to Files. Settings are changing, so follow Google’s current Timeline guide if your menus differ.

    -

    Keep that archive separately. iso.me does not import Google Timeline files; the Google Timeline comparison explains the tradeoffs before you change your recording setup.

    +

    Keep that archive separately. The verified App Store 1.7.16 build does not import Google Timeline files; the Google Timeline comparison explains the tradeoffs before you change your recording setup.

    @@ -282,5 +282,6 @@

    Remember your next trip.
    Start recording before you go.

    + diff --git a/marketing/public/compare/google-maps-timeline/index.html b/marketing/public/compare/google-maps-timeline/index.html index 237467a6..798c7dad 100644 --- a/marketing/public/compare/google-maps-timeline/index.html +++ b/marketing/public/compare/google-maps-timeline/index.html @@ -135,7 +135,7 @@
    @@ -158,7 +158,7 @@

    Compare the everyday workflow

    Storage and backupLocal journal. Keep supported export files for restoration; no built-in cloud sync.Device history, with optional encrypted server backup. RecordingStart and Stop control GPS recording and visit monitoring together. Always permission allows background recording.Visits and routes collected with Timeline enabled. FilesJSON, CSV, Markdown, GPX, KML, GeoJSON, OwnTracks, and Overland. Paid export; free preview.Location-history JSON export. - Moving existing historyImports supported iso.me visit and point files. No Google Timeline importer.Timeline backup can transfer history to another device. + Moving existing historyApp Store 1.7.16 imports iso.me JSON, CSV, and Markdown files. No Google Timeline import in that build.Timeline backup can transfer history to another device. PaymentFree recording. US lifetime unlock: $19.99 Individual or $39.99 Family. Regional prices vary.Timeline is available within Google Maps. @@ -175,7 +175,7 @@

    When iso.me fits

  • You want an optional webhook workflow alongside a local journal.
  • Use the private location journal guide to set up your first recording. Start enables detailed GPS as well as visit monitoring; there is no separate passive visit-only switch. Permissions, GPS conditions, and battery can affect the record.

    -

    Try free tracking on iPhone

    +

    Try free tracking on iPhone

    @@ -186,7 +186,7 @@

    When keeping Google Timeline makes sense

    Preserve your existing history first

    -

    Save Google’s exported archive separately before changing apps or devices. iso.me cannot import that archive or reconstruct earlier movement.

    +

    Save Google’s exported archive separately before changing apps or devices. App Store 1.7.16 cannot import that archive. A future importer still cannot reconstruct records missing from the file.

    For existing Apple or Google records, start with the iPhone history guide. For new iso.me routes, follow the GPX export walkthrough and check export and restore compatibility. A GPX file is useful for drawing a route elsewhere, but it cannot be imported into iso.me. Keep supported visit and point exports for records you want to restore later.

    @@ -204,7 +204,7 @@

    Understand what local storage means

    Record your next route.
    Keep a copy you can use.

    Start with free tracking, then decide whether you need the optional export unlock.

    - Download free for iPhone + Download free for iPhone
    @@ -259,5 +259,6 @@

    Record your next route.
    Keep a copy you can use.

    })(); + diff --git a/marketing/public/compare/index.html b/marketing/public/compare/index.html index a4de0e56..9e45abed 100644 --- a/marketing/public/compare/index.html +++ b/marketing/public/compare/index.html @@ -188,5 +188,6 @@ })(); + diff --git a/marketing/public/contact.html b/marketing/public/contact.html index a8558ef0..f2fd987e 100644 --- a/marketing/public/contact.html +++ b/marketing/public/contact.html @@ -194,5 +194,6 @@ })(); + diff --git a/marketing/public/docs/apple-watch/index.html b/marketing/public/docs/apple-watch/index.html index 0ebb8a53..c6099949 100644 --- a/marketing/public/docs/apple-watch/index.html +++ b/marketing/public/docs/apple-watch/index.html @@ -473,5 +473,6 @@

    Keep a portable copy after syncing

    })(); + diff --git a/marketing/public/docs/automatic-exports/index.html b/marketing/public/docs/automatic-exports/index.html index c660094d..0a552eca 100644 --- a/marketing/public/docs/automatic-exports/index.html +++ b/marketing/public/docs/automatic-exports/index.html @@ -458,5 +458,6 @@

    Manual control

    })(); + diff --git a/marketing/public/docs/export-import/index.html b/marketing/public/docs/export-import/index.html index ee6f8d73..45c6b835 100644 --- a/marketing/public/docs/export-import/index.html +++ b/marketing/public/docs/export-import/index.html @@ -400,7 +400,7 @@

    Saving and sharing

    Pick a default folder (with auto-save on by default) and exports land there silently with a confirmation toast; otherwise the standard share sheet appears. The Preview button renders everything without writing — free, and a good way to sanity-check filters. Single outings can also be exported straight from their detail page.

    Import

    -

    Settings → Import file accepts visit and point files exported from iso.me as JSON, CSV, or Markdown. Importing is free. A matching file extension alone does not make another app's file compatible: Google Timeline archives are not supported.

    +

    Settings → Import file accepts visit and point files exported from iso.me as JSON, CSV, or Markdown. Importing is free. A matching file extension alone does not make another app's file compatible: The verified App Store 1.7.16 build does not support Google Timeline archives; its importer also lacks the newer preview and duplicate checks.

    @@ -492,5 +492,6 @@

    Keep a copy and check it

    })(); + diff --git a/marketing/public/docs/getting-started/index.html b/marketing/public/docs/getting-started/index.html index 12885f2c..0a9119cb 100644 --- a/marketing/public/docs/getting-started/index.html +++ b/marketing/public/docs/getting-started/index.html @@ -453,5 +453,6 @@

    Replay the intro

    })(); + diff --git a/marketing/public/docs/index.html b/marketing/public/docs/index.html index 5e1f8b99..8ec4e140 100644 --- a/marketing/public/docs/index.html +++ b/marketing/public/docs/index.html @@ -489,5 +489,6 @@

    Privacy & your data

    })(); + diff --git a/marketing/public/docs/photos/index.html b/marketing/public/docs/photos/index.html index 0a802e7e..cae0358f 100644 --- a/marketing/public/docs/photos/index.html +++ b/marketing/public/docs/photos/index.html @@ -450,5 +450,6 @@

    Controls

    })(); + diff --git a/marketing/public/docs/places/index.html b/marketing/public/docs/places/index.html index ea1a0ea2..6213474d 100644 --- a/marketing/public/docs/places/index.html +++ b/marketing/public/docs/places/index.html @@ -456,5 +456,6 @@

    The current-place suggestion

    })(); + diff --git a/marketing/public/docs/privacy-data/index.html b/marketing/public/docs/privacy-data/index.html index 8c626cb2..201a9d97 100644 --- a/marketing/public/docs/privacy-data/index.html +++ b/marketing/public/docs/privacy-data/index.html @@ -460,5 +460,6 @@

    Permissions iso.me requests

    })(); + diff --git a/marketing/public/docs/siri-shortcuts/index.html b/marketing/public/docs/siri-shortcuts/index.html index 7457991c..36a31af6 100644 --- a/marketing/public/docs/siri-shortcuts/index.html +++ b/marketing/public/docs/siri-shortcuts/index.html @@ -450,5 +450,6 @@

    Automation ideas

    })(); + diff --git a/marketing/public/docs/timeline-outings/index.html b/marketing/public/docs/timeline-outings/index.html index c07ceb96..9c1cba54 100644 --- a/marketing/public/docs/timeline-outings/index.html +++ b/marketing/public/docs/timeline-outings/index.html @@ -382,6 +382,11 @@

    Route replay

    Sorting

    Outing lists can be sorted by newest, oldest, longest duration, distance, or point count.

    If a recorded day looks incomplete, follow the missing visits and route points checklist before deleting records or retrying an import.

    + + +

    Country Days

    +

    Timeline → Country Days counts local dates represented by visits, route points, and manual stays. Review this year, the last 365 days, or all time. A travel date can count in more than one country; gaps are not filled automatically. Viewing and manual stays are free; writing the country-date CSV uses the export purchase.

    +

    See how to track days spent in each country for timezone, network-geocoding, and counting details.

    @@ -1223,7 +1223,7 @@

    Start tracking to record your own routes and detect visits, then review the day on your iPhone. No account. No iso.me location server. Recording is free; portable exports are an optional purchase.

    - + @@ -1423,9 +1423,16 @@

    Photos on the map

    +
    + +
    @@ -1709,7 +1716,7 @@

    Install it first. Unlock export only when it matters.

  • Apple paymentsHandled by App Store
  • @@ -1791,7 +1798,7 @@

    Practical answers before you hand over location permission.

    Privacy Terms Support - App Store + App Store @@ -1843,5 +1850,6 @@

    Practical answers before you hand over location permission.

    })(); + diff --git a/marketing/public/openapi.json b/marketing/public/openapi.json index 9b82e048..3085697a 100644 --- a/marketing/public/openapi.json +++ b/marketing/public/openapi.json @@ -1,9 +1,9 @@ { "openapi": "3.1.0", "info": { - "title": "iso.me Public Product Metadata API", + "title": "iso.me Website API", "version": "1.0.0", - "description": "Read-only public app capabilities and documentation links. No account, credentials, personal locations, exports, or journal records are accessible through this API.", + "description": "Read-only public product metadata and a validated browser measurement endpoint for daily aggregate counts. No account, credentials, personal locations, exports, or journal records are accessible through this API.", "contact": { "name": "Cody Bontecou", "email": "cody.bontecou@gmail.com", @@ -46,7 +46,8 @@ "Timeline and outings", "Independent Apple Watch recording", "Portable export", - "Supported import", + "Supported iso.me file import (App Store 1.7.16)", + "Country Days and manual stays", "Siri and Shortcuts", "Optional outbound webhooks" ], @@ -113,6 +114,85 @@ } } } + }, + "/api/v1/acquisition": { + "post": { + "operationId": "countWebsiteAcquisition", + "summary": "Count a gated website page load or App Store link activation", + "description": "Internal browser measurement endpoint. Same-origin requests only, after the analytics exclusion gate. Accepts public page paths and coarse dimensions; no visitor identifiers or journal data. Updates daily aggregate counters. Does not measure installs or purchases.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "event", + "page", + "placement", + "source" + ], + "properties": { + "event": { + "type": "string", + "enum": [ + "page_view", + "app_store_clicked" + ] + }, + "page": { + "type": "string", + "description": "An exact known public page path without a query or fragment." + }, + "placement": { + "type": "string", + "enum": [ + "page", + "header", + "inline", + "footer", + "qr" + ] + }, + "source": { + "type": "string", + "enum": [ + "direct", + "internal", + "search", + "other" + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Count accepted, or privacy preference honored without storing." + }, + "400": { + "description": "Invalid or unknown dimensions." + }, + "403": { + "description": "Origin or host rejected." + }, + "405": { + "description": "Use POST." + }, + "413": { + "description": "Payload exceeds 512 bytes." + }, + "415": { + "description": "Use application/json." + }, + "503": { + "description": "Measurement unavailable; no success claimed." + } + } + } } }, "components": { diff --git a/marketing/public/privacy.html b/marketing/public/privacy.html index 5ac30034..62433741 100644 --- a/marketing/public/privacy.html +++ b/marketing/public/privacy.html @@ -322,7 +322,7 @@

    Data Export

    You can export visits, route points, and outings at any time as JSON, CSV, Markdown, GeoJSON, GPX, KML, OwnTracks, or Overland. Exported files are generated locally on your device. What you do with exported data is your responsibility.

    Analytics and Tracking

    -

    iso.me contains no third-party analytics SDKs, no advertising frameworks, and no trackers from other companies. The only telemetry is the first-party onboarding analytics described under Network Requests: a short allowlist of funnel events with a random install identifier and no location content. This website (not the App) additionally uses Cloudflare Web Analytics, which does not use cookies and does not track you across other sites.

    +

    iso.me contains no third-party analytics SDKs, no advertising frameworks, and no trackers from other companies. The only telemetry is the first-party onboarding analytics described under Network Requests: a short allowlist of funnel events with a random install identifier and no location content. This website (not the App) additionally uses Cloudflare Web Analytics, which does not use cookies and does not track you across other sites. After the existing analytics exclusion check allows measurement, the website also counts page loads and App Store link activations by public page, link placement, UTC day, and a coarse referrer category (search, internal, other, or direct). These counters use no cookies, browser storage, visitor identifiers, raw referrer URLs, query strings, or location files. They measure activations, not unique visitors, installs, or purchases. This collection is disabled when the browser sends Global Privacy Control or Do Not Track. Cloudflare hosts the aggregate counters. On selected acquisition pages, App Store download links also include a public campaign label and developer provider token so Apple can report campaign downloads and purchases subject to its reporting rules. These labels contain no personal information or location records.

    Third-Party Services

      @@ -408,5 +408,6 @@

      Contact

      })(); + diff --git a/marketing/public/screenshots/country-days.webp b/marketing/public/screenshots/country-days.webp new file mode 100644 index 00000000..568b4b61 Binary files /dev/null and b/marketing/public/screenshots/country-days.webp differ diff --git a/marketing/public/sitemap.xml b/marketing/public/sitemap.xml index c8c9985c..30a01624 100644 --- a/marketing/public/sitemap.xml +++ b/marketing/public/sitemap.xml @@ -35,6 +35,10 @@ https://isome.isolated.tech/blog/record-iphone-route-gpx/ 2026-10-26 + + https://isome.isolated.tech/blog/track-days-in-country-iphone/ + 2026-10-26 + https://isome.isolated.tech/blog/view-location-history-iphone/ 2026-10-26 diff --git a/marketing/public/terms.html b/marketing/public/terms.html index 1c7570a1..527de50e 100644 --- a/marketing/public/terms.html +++ b/marketing/public/terms.html @@ -405,5 +405,6 @@

      13 — Contact

      })(); + diff --git a/marketing/queries/acquisition.sql b/marketing/queries/acquisition.sql new file mode 100644 index 00000000..05df62f6 --- /dev/null +++ b/marketing/queries/acquisition.sql @@ -0,0 +1,8 @@ +-- UTC days, page loads and activations; never unique people or installs. +SELECT day, page, source, + SUM(CASE WHEN event = 'page_view' THEN count ELSE 0 END) AS page_loads, + SUM(CASE WHEN event = 'app_store_clicked' THEN count ELSE 0 END) AS download_activations +FROM website_acquisition_daily +WHERE day >= date('now', '-28 days') +GROUP BY day, page, source +ORDER BY day DESC, page, source; diff --git a/marketing/scripts/acquisition.test.mjs b/marketing/scripts/acquisition.test.mjs new file mode 100644 index 00000000..db312c65 --- /dev/null +++ b/marketing/scripts/acquisition.test.mjs @@ -0,0 +1,90 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; +import vm from 'node:vm'; + +const source = (await readFile(new URL('../worker.js', import.meta.url), 'utf8')) + .replace('__PAGE_MARKDOWN__', JSON.stringify({ '/': '/_markdown/index.md', '/blog/': '/_markdown/blog/index.md' })); +const worker = (await import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`)).default; +const client = await readFile(new URL('../public/assets/acquisition.js', import.meta.url), 'utf8'); +const valid = { event: 'app_store_clicked', page: '/', placement: 'inline', source: 'search' }; +function request(body = valid, headers = {}, method = 'POST') { + return new Request('https://isome.isolated.tech/api/v1/acquisition', { + method, headers: { Origin: 'https://isome.isolated.tech', 'Content-Type': 'application/json', ...headers }, + ...(method === 'POST' ? { body: typeof body === 'string' ? body : JSON.stringify(body) } : {}), + }); +} +function database() { + const calls = []; + return { calls, SEO_DB: { prepare(sql) { return { bind(...args) { return { async run() { calls.push({ sql, args }); } }; } }; } } }; +} + +test('accepts only public dimensions and binds values into an aggregate update', async () => { + const db = database(); + assert.equal((await worker.fetch(request(), db)).status, 204); + assert.deepEqual(db.calls[0].args, ['app_store_clicked', '/', 'inline', 'search']); + assert.match(db.calls[0].sql, /ON CONFLICT/); + assert.equal((await worker.fetch(request({ ...valid, event: 'page_view', placement: 'page' }), db)).status, 204); +}); + +test('rejects private fields, unknown pages, queries, methods and cross-origin submissions', async () => { + const db = database(); + for (const payload of [null, [], {}, { ...valid, latitude: 12 }, { ...valid, page: '/?secret=x' }, + { ...valid, page: '/unknown' }, { ...valid, source: 'https://private.example/path' }, + { ...valid, event: 'purchase' }, { ...valid, placement: 'page' }, '{']) { + assert.equal((await worker.fetch(request(payload), db)).status, 400); + } + assert.equal((await worker.fetch(request(valid, { Origin: 'https://other.example' }), db)).status, 403); + assert.equal((await worker.fetch(request(valid, { 'Content-Type': 'text/plain' }), db)).status, 415); + assert.equal((await worker.fetch(request(valid, {}, 'GET'), db)).status, 405); + assert.equal((await worker.fetch(request('x'.repeat(513)), db)).status, 413); + assert.equal(db.calls.length, 0); +}); + +test('honors browser privacy headers and reports an unavailable collector', async () => { + const db = database(); + for (const headers of [{ 'Sec-GPC': '1' }, { DNT: '1' }]) { + assert.equal((await worker.fetch(request(valid, headers), db)).status, 204); + } + assert.equal(db.calls.length, 0); + const result = await worker.fetch(request(), {}); + assert.equal(result.status, 503); + assert.equal(result.headers.get('Cache-Control'), 'no-store'); +}); + +async function browser({ track = true, fail = false, gpc = false, host = 'isome.isolated.tech' } = {}) { + const calls = []; + let click; + const context = { + location: { hostname: host, pathname: '/blog/' }, navigator: { globalPrivacyControl: gpc }, URL, + document: { referrer: 'https://www.google.com/search?q=sensitive', addEventListener(event, handler) { click = handler; } }, + fetch: async (url, options) => { + calls.push({ url, options }); + if (fail) throw new Error('gate unavailable'); + return { ok: true, json: async () => ({ track }) }; + }, + }; + vm.runInNewContext(client, context); + await new Promise(resolve => setImmediate(resolve)); + const link = { href: 'https://apps.apple.com/us/app/iso-me/id6761960794', dataset: {}, closest: () => null }; + click?.({ target: { closest: () => link } }); + await new Promise(resolve => setImmediate(resolve)); + return calls; +} + +test('client fails closed for exclusions, failed gate, GPC and previews', async () => { + for (const settings of [{ track: false }, { fail: true }, { gpc: true }, { host: 'preview.pages.dev' }]) { + const calls = await browser(settings); + assert.equal(calls.filter(c => c.url === '/api/v1/acquisition').length, 0); + } +}); + +test('client sends coarse page and click dimensions, never the search query or referrer', async () => { + const calls = (await browser()).filter(c => c.url === '/api/v1/acquisition'); + assert.equal(calls.length, 2); + assert.deepEqual(calls.map(c => JSON.parse(c.options.body)), [ + { event: 'page_view', page: '/blog/', placement: 'page', source: 'search' }, + { event: 'app_store_clicked', page: '/blog/', placement: 'inline', source: 'search' }, + ]); + assert.ok(calls.every(c => c.options.credentials === 'omit' && c.options.referrerPolicy === 'no-referrer' && !c.options.body.includes('sensitive'))); +}); diff --git a/marketing/scripts/build_agentic.py b/marketing/scripts/build_agentic.py index b94e285d..88b1b7dc 100644 --- a/marketing/scripts/build_agentic.py +++ b/marketing/scripts/build_agentic.py @@ -9,6 +9,7 @@ from build_seo_pages import render from check_site import BASE, PUBLIC, page_url from product_contract import build_product_contract +from campaign_links import update_download_links TRUST = [ { @@ -104,7 +105,7 @@ def handle_data(self, text): def result(self): text = ''.join(self.parts) text = re.sub(r'\n[ \t]+', '\n', text) - return re.sub(r'\n{3,}', '\n\n', text).strip() + '\n\nSource: ' + self.url + '\n' + return '\n'.join(line.rstrip() for line in re.sub(r'\n{3,}', '\n\n', text).strip().splitlines()) + '\n\nSource: ' + self.url + '\n' def build(): @@ -114,6 +115,7 @@ def build(): if page['path'] == '/404': content = content.replace('content="index,follow"', 'content="noindex,follow"') (PUBLIC / (page['path'].lstrip('/') + '.html')).write_text(content) + update_download_links() manifest = {} for source in sorted(PUBLIC.rglob('*.html')): if source.name == '404.html': diff --git a/marketing/scripts/build_docs.py b/marketing/scripts/build_docs.py index 861dd09a..4b193f96 100644 --- a/marketing/scripts/build_docs.py +++ b/marketing/scripts/build_docs.py @@ -262,7 +262,7 @@

      Pick a default folder (with auto-save on by default) and exports land there silently with a confirmation toast; otherwise the standard share sheet appears. The Preview button renders everything without writing — free, and a good way to sanity-check filters. Single outings can also be exported straight from their detail page.

      Import

      -

      Settings → Import file accepts visit and point files exported from iso.me as JSON, CSV, or Markdown. Importing is free. A matching file extension alone does not make another app's file compatible: Google Timeline archives are not supported.

      +

      Settings → Import file accepts visit and point files exported from iso.me as JSON, CSV, or Markdown. Importing is free. A matching file extension alone does not make another app's file compatible: The verified App Store 1.7.16 build does not support Google Timeline archives; its importer also lacks the newer preview and duplicate checks.

    Choose a file for the next task
    FormatUseful forImport into iso.me
    @@ -428,6 +428,13 @@ """ +# Country Days is present in verified public 1.7.16 build 46. +BODIES["timeline-outings"] += """ +

    Country Days

    +

    Timeline → Country Days counts local dates represented by visits, route points, and manual stays. Review this year, the last 365 days, or all time. A travel date can count in more than one country; gaps are not filled automatically. Viewing and manual stays are free; writing the country-date CSV uses the export purchase.

    +

    See how to track days spent in each country for timezone, network-geocoding, and counting details.

    +""" + BODIES["privacy-data"] = """

    The short version

    Your location history — visits, routes, outings, saved places, photo matches — is stored in the app's on-device database and nowhere else. There is no iso.me account, no cloud sync, and no iso.me server holding your location data. The full legal text is the Privacy Policy; this guide is the plain-language version.

    diff --git a/marketing/scripts/build_seo_pages.py b/marketing/scripts/build_seo_pages.py index 098470ba..a0a2f0de 100644 --- a/marketing/scripts/build_seo_pages.py +++ b/marketing/scripts/build_seo_pages.py @@ -10,6 +10,16 @@ APP = "https://apps.apple.com/us/app/iso-me/id6761960794" REVIEWED = "2026-10-26" PAGES = [ + { + "path": "/blog/track-days-in-country-iphone/", + "section": "Guides", "section_path": "/blog/", "breadcrumb": "Country days", + "type": "BlogPosting", + "title": "Track Days Spent in Each Country on iPhone — iso.me", + "headline": "How to track days spent in each country on iPhone", + "description": "Count country dates from recorded visits, GPS points, and manual stays in iso.me. Understand travel days, timezones, gaps, and optional CSV export.", + "lede": "Review country totals and the dates behind them, add missing stays, and keep a personal record without an iso.me account.", + "source": "track-days-in-country-iphone.html", + }, { "path": "/compare/", "title": "Compare iPhone Location Journals — iso.me", @@ -105,8 +115,26 @@ ] +# Not generated into public/ until the supporting App Store build is verified. +DRAFTS = [{ + "path": "/blog/import-google-timeline-iphone/", "section": "Guides", "section_path": "/blog/", + "breadcrumb": "Import Google Timeline", "type": "BlogPosting", "robots": "noindex,follow", + "title": "Import Google Timeline on iPhone — Release Preview — iso.me", + "headline": "How to import Google Timeline into iso.me on iPhone", + "description": "A release-preview walkthrough of supported Google JSON files, import preview, duplicate checks, and preserving the original archive.", + "lede": "Prepared for the next supporting release. The verified public 1.7.16 build does not include this importer.", + "source": "import-google-timeline-iphone.html", +}] + + # Keep next steps specific to the task on each page. -RELATED = {'/blog/view-location-history-iphone/': [('/blog/missing-location-history-iphone/', +RELATED = { + '/blog/track-days-in-country-iphone/': [ + ('/blog/private-location-journal-iphone/', 'Record your next trip', + 'Start a local journal before you leave.'), + ('/blog/back-up-iphone-location-history/', 'Keep the underlying records', + 'A country-date summary is not a complete backup.')], + '/blog/view-location-history-iphone/': [('/blog/missing-location-history-iphone/', 'Check missing iso.me records', 'Diagnose recording gaps, hidden points, Watch ' 'transfers, and export filters.'), @@ -200,7 +228,7 @@ def render(page): {escape(page["title"])} - + diff --git a/marketing/scripts/build_site.py b/marketing/scripts/build_site.py index 27dd844f..a33a107a 100644 --- a/marketing/scripts/build_site.py +++ b/marketing/scripts/build_site.py @@ -16,6 +16,7 @@ "/compare/", "/compare/google-maps-timeline/", "/blog/view-location-history-iphone/", "/blog/record-iphone-route-gpx/", "/blog/iphone-location-journal-obsidian/", + "/blog/track-days-in-country-iphone/", "/blog/missing-location-history-iphone/", "/blog/iphone-location-tracking-battery/", "/blog/back-up-iphone-location-history/", "/docs/apple-watch/", "/docs/webhooks/", "/docs/timeline-outings/", @@ -26,6 +27,18 @@ def build(): for script in ("build_docs.py", "build_seo_pages.py", "build_agentic.py"): subprocess.run([sys.executable, str(SCRIPTS / script)], check=True) + # Include one shared, gated acquisition listener on every public page. + acquisition = '' + for page in PUBLIC.rglob('*.html'): + content = page.read_text() + if acquisition not in content: + page.write_text(content.replace('', acquisition + '\n')) + + from build_seo_pages import DRAFTS + for draft in DRAFTS: + if (PUBLIC / draft['path'].strip('/') / 'index.html').exists(): + raise ValueError(f"Release-gated draft leaked into public/: {draft['path']}") + namespace = "http://www.sitemaps.org/schemas/sitemap/0.9" ET.register_namespace("", namespace) sitemap_path = PUBLIC / "sitemap.xml" diff --git a/marketing/scripts/campaign_links.py b/marketing/scripts/campaign_links.py new file mode 100644 index 00000000..c65cdb57 --- /dev/null +++ b/marketing/scripts/campaign_links.py @@ -0,0 +1,35 @@ +"""Apply a genuine Apple provider token to the four measured acquisition pages.""" +from html import escape +import json +from pathlib import Path +import re +from urllib.parse import urlencode +from check_site import PUBLIC, page_url, BASE + +APP = 'https://apps.apple.com/us/app/iso-me/id6761960794' +CONFIG = PUBLIC.parent / 'content/acquisition.json' + + +def app_url(path): + config = json.loads(CONFIG.read_text()) + token = config.get('providerToken') + campaign = config['campaigns'].get(path) + if token is None or campaign is None: + return APP + if not isinstance(token, str) or not re.fullmatch(r'[0-9]+', token): + raise ValueError('Use the actual numeric provider token from an Apple-generated campaign link.') + return 'https://apps.apple.com/app/apple-store/id6761960794?' + urlencode({'pt': token, 'ct': campaign, 'mt': '8'}) + + +def update_download_links(): + pattern = re.compile(r'(]*?\bhref=["\'])https://apps\.apple\.com/(?:us/)?app/(?:(?:iso-me|apple-store)/)?id6761960794(?:\?[^"\']*)?(["\'])') + for page in PUBLIC.rglob('*.html'): + url = app_url(page_url(page).removeprefix(BASE)) + original = page.read_text() + updated = pattern.sub(lambda match: match[1] + escape(url, quote=True) + match[2], original) + if updated != original: + page.write_text(updated) + # A mismatched QR must never silently send desktop readers to an old campaign. + declared = PUBLIC / 'assets/app-store-qr-url.txt' + if declared.read_text().strip() != app_url('/'): + raise ValueError('Regenerate the App Store QR and its URL file after changing the provider token.') diff --git a/marketing/scripts/check_site.py b/marketing/scripts/check_site.py index 369393f1..65e24edb 100644 --- a/marketing/scripts/check_site.py +++ b/marketing/scripts/check_site.py @@ -116,7 +116,17 @@ def check(): page.errors.append(f"duplicate IDs: {duplicates}") checked_links = 0 + from campaign_links import app_url, CONFIG + campaign_config = json.loads(CONFIG.read_text()) for path, page in pages.items(): + public_path = page_url(path).removeprefix(BASE) + download_links = [target for target, kind in page.targets + if kind == 'href' and urlsplit(target).hostname == 'apps.apple.com' + and 'id6761960794' in urlsplit(target).path] + if public_path in campaign_config['campaigns'] and not download_links: + page.errors.append('missing campaign download anchor') + if any(target != app_url(public_path) for target in download_links): + page.errors.append('download campaign does not match this page') for target, kind in page.targets: url = urlsplit(urljoin(page_url(path), target)) if url.scheme not in ("https", "http") or url.netloc != urlsplit(BASE).netloc: diff --git a/marketing/scripts/preview_drafts.py b/marketing/scripts/preview_drafts.py new file mode 100644 index 00000000..b75b2250 --- /dev/null +++ b/marketing/scripts/preview_drafts.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +"""Render release-gated articles outside the public deployment directory.""" +import argparse +from pathlib import Path +from build_seo_pages import DRAFTS, render + +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument('--output', type=Path, default=Path('/tmp/isome-seo-drafts')) +args = parser.parse_args() +public = Path(__file__).resolve().parents[1] / 'public' +if args.output.resolve().is_relative_to(public.resolve()): + parser.error('Draft previews must stay outside public/.') +args.output.mkdir(parents=True, exist_ok=True) +for page in DRAFTS: + output = args.output / (page['path'].strip('/').replace('/', '-') + '.html') + output.write_text(render(page)) + print(output) diff --git a/marketing/scripts/product_contract.py b/marketing/scripts/product_contract.py index de019cf3..ab5676a0 100644 --- a/marketing/scripts/product_contract.py +++ b/marketing/scripts/product_contract.py @@ -21,7 +21,7 @@ def build_product_contract(): 'appStore': 'https://apps.apple.com/us/app/iso-me/id6761960794', 'sourceRepository': 'https://github.com/CodyBontecou/isome', 'platforms': ['iOS 17 or later', 'watchOS 10 or later'], - 'capabilities': ['Visit detection during tracking', 'GPS route recording', 'Timeline and outings', 'Independent Apple Watch recording', 'Portable export', 'Supported import', 'Siri and Shortcuts', 'Optional outbound webhooks'], + 'capabilities': ['Visit detection during tracking', 'GPS route recording', 'Timeline and outings', 'Independent Apple Watch recording', 'Portable export', 'Supported iso.me file import (App Store 1.7.16)', 'Country Days and manual stays', 'Siri and Shortcuts', 'Optional outbound webhooks'], 'exportFormats': ['JSON', 'CSV', 'Markdown', 'GeoJSON', 'GPX', 'KML', 'OwnTracks', 'Overland'], 'pricingURL': BASE + '/#pricing', 'privacyURL': BASE + '/privacy', @@ -46,7 +46,7 @@ def build_product_contract(): } spec = { 'openapi': '3.1.0', - 'info': {'title': 'iso.me Public Product Metadata API', 'version': '1.0.0', 'description': 'Read-only public app capabilities and documentation links. No account, credentials, personal locations, exports, or journal records are accessible through this API.', 'contact': {'name': 'Cody Bontecou', 'email': 'cody.bontecou@gmail.com', 'url': BASE + '/contact'}}, + 'info': {'title': 'iso.me Website API', 'version': '1.0.0', 'description': 'Read-only public product metadata and a validated browser measurement endpoint for daily aggregate counts. No account, credentials, personal locations, exports, or journal records are accessible through this API.', 'contact': {'name': 'Cody Bontecou', 'email': 'cody.bontecou@gmail.com', 'url': BASE + '/contact'}}, 'servers': [{'url': BASE}], 'security': [], 'paths': {'/api/v1/product': {'get': { @@ -63,6 +63,27 @@ def build_product_contract(): 'Problem': {'type': 'object', 'required': ['type', 'title', 'status', 'detail', 'resolution'], 'properties': {'type': uri, 'title': string, 'status': {'type': 'integer'}, 'detail': string, 'resolution': string}}, }}, } + spec['paths']['/api/v1/acquisition'] = {'post': { + 'operationId': 'countWebsiteAcquisition', + 'summary': 'Count a gated website page load or App Store link activation', + 'description': 'Internal browser measurement endpoint. Same-origin requests only, after the analytics exclusion gate. Accepts public page paths and coarse dimensions; no visitor identifiers or journal data. Updates daily aggregate counters. Does not measure installs or purchases.', + 'requestBody': {'required': True, 'content': {'application/json': {'schema': { + 'type': 'object', 'additionalProperties': False, + 'required': ['event', 'page', 'placement', 'source'], + 'properties': { + 'event': {'type': 'string', 'enum': ['page_view', 'app_store_clicked']}, + 'page': {'type': 'string', 'description': 'An exact known public page path without a query or fragment.'}, + 'placement': {'type': 'string', 'enum': ['page', 'header', 'inline', 'footer', 'qr']}, + 'source': {'type': 'string', 'enum': ['direct', 'internal', 'search', 'other']}, + }, + }}}}, + 'responses': {str(code): {'description': description} for code, description in [ + (204, 'Count accepted, or privacy preference honored without storing.'), + (400, 'Invalid or unknown dimensions.'), (403, 'Origin or host rejected.'), + (405, 'Use POST.'), (413, 'Payload exceeds 512 bytes.'), + (415, 'Use application/json.'), (503, 'Measurement unavailable; no success claimed.'), + ]}, + }} target = PUBLIC / 'api/v1/product.json' target.parent.mkdir(parents=True, exist_ok=True) target.write_text(json.dumps(product, indent=2) + '\n') diff --git a/marketing/worker.js b/marketing/worker.js index 5eb6f477..612a8423 100644 --- a/marketing/worker.js +++ b/marketing/worker.js @@ -1,6 +1,50 @@ // The site builder replaces this token with the public-page Markdown manifest. const pages = __PAGE_MARKDOWN__; +async function acquisition(request, env) { + const headers = { 'Cache-Control': 'no-store' }; + const reply = (message, status) => new Response(message, { status, headers }); + if (request.method !== 'POST') return new Response(null, { status: 405, headers: { ...headers, Allow: 'POST' } }); + const url = new URL(request.url); + // Reject cross-origin/form submissions. Preview deployments don't collect counts. + if (request.headers.get('Origin') !== url.origin || + !(url.hostname === 'isome.isolated.tech' || ['127.0.0.1', 'localhost'].includes(url.hostname))) return reply('Forbidden', 403); + if (request.headers.get('Content-Type')?.split(';')[0].trim() !== 'application/json') return reply('JSON required', 415); + if (request.headers.get('Sec-GPC') === '1' || request.headers.get('DNT') === '1') return reply(null, 204); + if (!env.SEO_DB) return reply('Measurement unavailable', 503); + if (Number(request.headers.get('Content-Length')) > 512) return reply('Payload too large', 413); + let size = 0; + const chunks = []; + const reader = request.body?.getReader(); + if (!reader) return reply('Invalid event', 400); + while (true) { + const { done, value } = await reader.read(); + if (done) break; + size += value.byteLength; + if (size > 512) { await reader.cancel(); return reply('Payload too large', 413); } + chunks.push(value); + } + let event; + try { + const bytes = new Uint8Array(size); + let offset = 0; + for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.byteLength; } + event = JSON.parse(new TextDecoder().decode(bytes)); + } catch { return reply('Invalid event', 400); } + if (!event || Array.isArray(event) || Object.keys(event).sort().join(',') !== 'event,page,placement,source' || + !['page_view', 'app_store_clicked'].includes(event.event) || + !Object.hasOwn(pages, event.page) || + !['page', 'header', 'inline', 'footer', 'qr'].includes(event.placement) || + !['direct', 'internal', 'search', 'other'].includes(event.source) || + (event.event === 'page_view') !== (event.placement === 'page')) return reply('Invalid event', 400); + try { + await env.SEO_DB.prepare(`INSERT INTO website_acquisition_daily (day,event,page,placement,source,count) + VALUES (date('now'),?,?,?,?,1) ON CONFLICT(day,event,page,placement,source) + DO UPDATE SET count=count+1`).bind(event.event, event.page, event.placement, event.source).run(); + } catch { return reply('Measurement unavailable', 503); } + return reply(null, 204); +} + function quality(accept, type) { for (const entry of accept.toLowerCase().split(',')) { const [media, ...parameters] = entry.trim().split(';'); @@ -15,6 +59,7 @@ function quality(accept, type) { export default { async fetch(request, env) { const url = new URL(request.url); + if (url.pathname === '/api/v1/acquisition') return acquisition(request, env); if (request.method !== 'GET' && request.method !== 'HEAD') { return new Response(JSON.stringify({ type: 'about:blank', title: 'Method not allowed', status: 405, diff --git a/marketing/wrangler.jsonc b/marketing/wrangler.jsonc new file mode 100644 index 00000000..84e062d3 --- /dev/null +++ b/marketing/wrangler.jsonc @@ -0,0 +1,11 @@ +{ + "name": "spotted", + "pages_build_output_dir": "./public", + "compatibility_date": "2026-04-08", + "d1_databases": [{ + "binding": "SEO_DB", + "database_name": "iso-me-onboarding-analytics", + "database_id": "20e95c7d-0939-4ead-8066-f2207505d273", + "migrations_dir": "./migrations" + }] +}
    Choose a file for the next task
    FormatUseful forImport into iso.me