In the documentation I'm reading:
It is possible save the latitude and longitude of the device in various ways:
But I can only see an example how to do it via an API. Can it be done directly?
Hi Wouter,
Short answer: the API is the way to save to your database, and for background tracking it's the only reliable one. Here's why, and how to set it up cleanly.
Why there's no "direct" save The tracking runs natively in the background, outside your app's OutSystems client logic, and keeps running when the app is minimized or closed. At that point no client or server action of yours can run, so the plugin sends each fix by HTTP POST to the URLs you configure. Your ODC database is only reachable from server logic, so an exposed REST API whose logic writes to an entity is the "database" option in practice. The id field in the location parameters refers to the plugin's own local store on the device, where it keeps fixes while offline before sending them to the second (batch) API.
id
Setup in ODC 1. Create a DeviceLocation entity: UserId, DeviceId, Latitude, Longitude (Decimal), Accuracy, Speed, Provider, RecordedOn (DateTime), plus an index on (UserId, RecordedOn). 2. In a server app, expose a REST API with two POST methods matching the plugin's PostTemplate: - SaveLocation (one location) - SaveLocations (list, used for the offline/retry batch) 3. In each method convert time (UTC milliseconds since 1970) to DateTime with AddSeconds(NewDateTime(1970,1,1,0,0,0), DecimalToInteger(time / 1000)), then CreateDeviceLocation. 4. Point the plugin's URL settings in StartTracking to those two endpoints.
DeviceLocation
SaveLocation
SaveLocations
time
AddSeconds(NewDateTime(1970,1,1,0,0,0), DecimalToInteger(time / 1000))
CreateDeviceLocation
StartTracking
Make it production-ready - Authenticate: since the plugin lets you set and change headers at runtime, send a per-user token in a header when you call StartTracking, and validate it in the API's OnAuthentication. Without it, anyone who finds the URL can write locations. - Deduplicate: the batch API can resend fixes that already arrived. Before inserting, skip records with the same DeviceId + RecordedOn (or add a unique index on them). - Filter noise: ignore fixes with poor accuracy (e.g. above 100 m) and reject ones where isFromMockProvider is true on Android if location integrity matters. - Keep it small: add a Timer that purges or aggregates old rows, because continuous tracking grows the table fast.
accuracy
isFromMockProvider
If you only need locations while the app is open, you can skip the plugin's sync entirely: get the position in a client action and call a server action that creates the record. But for true background tracking, the API route is the right design.
Hope this helps!
What do you mean with "the plugin's PostTemplate"?
Hi Wouter, good question, I should have explained that term.
PostTemplate is a setting of the plugin itself. Step 3 of the plugin’s Forge documentation describes it as “the JSON structure sent to the API during the tracking”. You find it in the JavaScript of the plugin’s StartTracking action.
Think of it as a form the plugin fills in for every location it records: you decide the field names, and the plugin puts the real values in them. The values you can use are the ones listed in the documentation’s “Location parameter” table (latitude, longitude, time, accuracy, speed, etc.).
For example, if your template has the fields lat, lng, recordedAt and accuracy, mapped to latitude, longitude, time and accuracy, each location reaches your API as: { "lat": 23.5880, "lng": 58.3829, "recordedAt": 1760000000000, "accuracy": 12 }
So the steps are:
Hope this makes it clearer!