Overview
Fleet Tracker adds true location history to devices you already manage in Microsoft Intune — a continuous breadcrumb trail retained well beyond Intune's short built-in window, on both Android and Windows.
Each managed device runs a lightweight agent that posts its location on a regular interval. The server groups devices by a fleet tag you assign, and the dashboard shows a live map, trails, a searchable history log, and a replay of any device's movements. Personal identity (the signed-in user's email) is encrypted before it is stored, so it is visible only to people who hold that fleet's key — not to the database or the server operator.
How it works
- An agent runs on each device — the Android app (Managed Google Play) or the Windows agent. It collects location in the background and survives reboot on properly managed devices.
- It posts pings to the server — every few minutes the agent sends a small JSON ping (location + device IDs + fleet tag) to
POST /api/location, authenticated with an ingest API key. - The server groups & secures it — pings are stored by fleet tag; the user's email/UPN/name is sealed to that fleet's public key so only key-holders can read it.
- You watch it on the dashboard — live map, trails, history, replay, and per-fleet access scoping for your team.
Before you start
You'll want these ready regardless of platform:
- Intune admin access (or an MDM/Entra admin role).
- A device group in Intune containing the enrolled, corporate-owned devices you want to track.
- The agent package — the Fleet Tracker APK for Android, or the Windows agent installer for Windows.
- An ingest API key — every ping needs one. Use a master key in the server's
.env, or issue per-device keys from the admin console. See Ingest API key. - (Recommended) a PII key per fleet tag so user emails are captured and readable to you. See Privacy & PII keys.
fleetTag. It's how the dashboard groups devices and how access is scoped — create one Intune configuration per fleet/company so each gets the right tag.🤖 Android Deploy on Android (Intune)
Distribution is through Managed Google Play as a private app, assigned by Intune. The flow:
- Publish the APK to Managed Google Play
Intune → Apps → Android → Add → Managed Google Play app. In the Play console that opens, create / publish a private app (the + button, lower-right), name it "Fleet Tracker", and upload the APK. Wait for Google to process it. Every later update needs a higherversionCode. - Sync it into Intune
Apps → Android → open Managed Google Play → Sync. The app appears in the list after the sync completes (a few minutes). - Assign it as Required
Open Fleet Tracker → Properties / Assignments, and under Required add the device group. Save — this auto-installs it. - Create an App Configuration Policy
Apps → Android → App configuration policies → Add → Managed devices. Set Platform = Android Enterprise, Targeted app = Fleet Tracker, Profile = Fully managed. Auto-grant the Location permissions (and Post notifications). Then in the Configuration Designer add the keys below. - Map the configuration keys (see table) — at minimum
fleetTag,serialNumber(ordeviceId),mail, and your ingest API key. Assign the policy to the same device group and Save. - Auto-grant permissions & protect the service
In the device/enrollment profile, set Default app permission policy = Auto grant so FINE + BACKGROUND location are granted silently, exempt Fleet Tracker from battery optimization, and on Samsung/Knox ensure the boot & foreground-service grants are present.
Configuration keys (Configuration Designer)
Hardware attributes (serial, device IDs) come from the dropdown in the designer — they can't be typed as {{token}} strings.
| Key | Intune value | Used for |
|---|---|---|
| fleetTag | Static text (e.g. "Acme") | Group / access scope (required) |
| serialNumber | Serial number | Stable device identity (or IMEI) |
| deviceId | Intune device ID | Identity fallback |
| deviceName | Device name | Friendly name on the map |
| Signed-in user's email (sealed) | ||
| X-API-Key | Static text (your ingest key) | Authorizes the ping (required) |
⊞ Windows Deploy on Windows (Intune)
The Windows agent installs as a standard Intune app. It runs in the background, identifies the machine by its Machine GUID, uses the hostname as the device name, and reports GPS- or IP-based location (it appears under the Windows platform filter on the dashboard).
- Package the agent
Wrap the Windows agent as a Win32 app (.intunewinvia the Microsoft Win32 Content Prep Tool) or use its MSI if provided. - Upload to Intune
Intune → Apps → Windows → Add → choose Windows app (Win32) (or Line-of-business for an MSI), and upload the package. Set the install/uninstall commands and a detection rule per your build. - Assign it as Required
Under Assignments → Required, add the device group. Save to push the install. - Provide the fleet tag & ingest key
The agent needs the same two values as Android: afleetTagand your ingest API key. Deliver them with whatever your agent build reads — an MSI property, an install-command argument, a registry value, or a config file dropped next to the executable. - Verify
After the install and the first ping interval, the machine appears on the dashboard withsource = windows_gpsorwindows_ipand a Windows badge.
fleetTag / ingest key depend on your specific Windows build. Use your agent's documented config method for those two values — everything else is standard Intune Win32/MSI deployment.The ingest API key (required)
POST /api/location is closed by default — every ping must carry a valid key, sent as an X-API-Key header (preferred) or Authorization: Bearer <key>. Anything else is rejected with 401 and the location is not stored.
Two ways to provision
- Master key (simplest) — set
INGEST_API_KEY=<long-random-value>in the server.env; every device sends that one value. - Per-device keys — an admin issues one key per device/customer from the admin console and can revoke a single device's key if a phone is lost.
401 and stop reporting. Emergency kill-switch: set INGEST_ENFORCE=0 in .env and restart to temporarily reopen ingest.Privacy & PII keys
User identity — email, UPN, name — is sealed (encrypted) to a public key before it is stored. The database and the server operator cannot read it; only a holder of the matching private key can. Device IDs, serial, fleet tag, and location stay readable (they're company assets, not personal data).
Keys are per fleet tag (one tenant = one keypair)
- Open the KEY pill in the dashboard — each fleet tag you can see has its own row.
- Generate & register — this makes a keypair in your browser, downloads the private-key backup (keep it safe), and registers the public key with the server. From then on that tag's pings are sealed to it.
- Read names anywhere — on another browser, KEY pill → Import a backup key to unlock. Without the key the dashboard shows "Encrypted".
- Manage — per tag you can Rotate, Backup, or Forget; admins also get "Remove key".
Using the dashboard
The dashboard is the live operations view of your fleet. Highlights:
Live map & markers
Every device's latest position, auto-refreshing. Selecting a device focuses the map on just that one to cut clutter.
Trails & history log
A breadcrumb path per device plus a searchable, time-stamped ping log going back well beyond Intune's window.
Replay
Scrub through a device's movement over time with play/pause and variable speed.
Filters & search
Filter by platform (Android / Windows) and fleet tag, and search devices by name or ID.
Hide devices
Per-browser hide for retired or noisy devices, with a toggle to show them again.
KEY pill
Per-fleet-tag identity keys — generate, import, rotate, back up, or forget — so emails are readable only to you.
Status badges
Freshness at a glance: a recent ping shows "1h"; a device silent for 7+ days shows "Stale".
Light / dark theme
A theme toggle in the header, remembered per browser across the whole site.
Admin console
The admin console (the Admin link, visible to admin accounts) is where you run the service.
Tenant overview & analytics
A per-fleet report card for the whole deployment: device counts with new / stale deltas, an Android / Windows split, ping volume, an apportioned storage estimate per tenant, assigned users, PII-key status, and last activity. A time-window filter (24h / 7d / 30d / 90d / 12 months) re-scopes the activity figures; lifetime totals stay cumulative.
Users & access
- Users — create, edit, and delete dashboard logins. Each non-admin user is scoped to one or more fleet tags; admins see everything.
- Manage Tags — pre-create fleet tags so they're assignable before any device reports, and remove tags (which unassigns them from every user; historical pings are preserved).
- API Keys — issue an ingest key per user/customer and revoke individual keys when a device is lost.
Verify & troubleshoot
After install, wait up to ~5 minutes (the ping interval) for the first location. The device should appear with its fleet tag, name, and serial/ID; the user's email shows only on a browser holding that tag's key.
| Symptom | What to check |
|---|---|
| App not installing | Confirm the Required assignment & group membership; Sync Managed Google Play; ensure the new versionCode is higher. |
| Config shows Pending | Force a Company Portal sync; confirm the policy targets the same group as the app; allow a few minutes to reach Succeeded. |
| No fleet tag / email | The App Configuration Policy isn't applied or the key isn't mapped — verify fleetTag and mail in the Configuration Designer. |
| No background pings (Samsung) | Confirm Location = "Allow all the time" was auto-granted and battery optimization is off. |
| Nothing after reboot (non-Samsung) | Open the app once (stopped-state), then confirm boot + background-location permissions are granted. |
| Pings rejected / 401 | The device isn't sending a valid ingest key. Set INGEST_API_KEY (or issue a per-device key) and have the agent send X-API-Key. |
| Email shows "Encrypted" | This browser doesn't hold that fleet tag's key. KEY pill → Import a backup, or Generate & register for the tag. |