OptionallocationOptional custom template for rendering Location JSON request data in HTTP uploads.
The locationTemplate is evaluated using Ruby-style ERB tags:
<%= variable_name %>
BackgroundGeolocation.ready({
persistence: {
locationTemplate:
'{"lat":<%= latitude %>,"lng":<%= longitude %>,"event":"<%= event %>",isMoving:<%= is_moving %>}'
}
});
// Or use a compact Array template:
BackgroundGeolocation.ready({
persistence: {
locationTemplate:
'[<%=latitude%>, <%=longitude%>, "<%=event%>", <%=is_moving%>]'
}
});
⚠️ Quoting string data
The plugin does not automatically insert quotes around string values.
Templates are JSON-encoded exactly as written.
The following will cause a JSON error because timestamp is a string
but is rendered unquoted:
BackgroundGeolocation.ready({
persistence: {
locationTemplate: '{"timestamp": <%= timestamp %>}'
}
});
This renders invalid JSON:
{"timestamp": 2018-01-01T12:01:01.123Z}
Correct usage:
BackgroundGeolocation.ready({
persistence: {
locationTemplate: '{"timestamp": "<%= timestamp %>"}'
}
});
{"timestamp": "2018-01-01T12:01:01.123Z"}
Configured extras
If extras are configured, the key/value pairs are merged directly into the rendered location JSON.
BackgroundGeolocation.ready({
http: {
url: 'https://my.server.com/locations',
rootProperty: 'data',
},
persistence: {
locationTemplate: '{"lat":<%= latitude %>,"lng":<%= longitude %>}',
extras: { foo: "bar" }
}
});
Produces:
{
"data": {
"lat": 23.23232323,
"lng": 37.37373737,
"foo": "bar"
}
}
Template Tags
| Tag | Type | Description |
|---|---|---|
latitude |
Float |
|
longitude |
Float |
|
speed |
Float |
Meters |
heading |
Float |
Degrees |
accuracy |
Float |
Meters |
altitude |
Float |
Meters |
altitude_accuracy |
Float |
Meters |
timestamp |
String |
ISO-8601 |
uuid |
String |
Unique ID |
event |
String |
motionchange, geofence, heartbeat, providerchange |
odometer |
Float |
Meters |
activity.type |
String |
still, on_foot, running, on_bicycle, in_vehicle, unknown |
activity.confidence |
Integer |
0–100% |
battery.level |
Float |
0–100% |
battery.is_charging |
Boolean |
Is device plugged in? |
mock |
Boolean |
True if generated by mock provider |
is_moving |
Boolean |
Device was moving when recorded |
timestampMeta |
Object |
Timestamp metadata; see GeoConfig.enableTimestampMeta |
ℹ️ See also
OptionalgeofenceOptional custom template for rendering GeofenceEvent JSON request data in HTTP uploads.
The geofenceTemplate behaves like
locationTemplate, but includes two
additional tags: geofence.identifier and geofence.action.
The template is evaluated using Ruby-style ERB tags:
<%= variable_name %>
ℹ️ See also
BackgroundGeolocation.ready({
persistence: {
geofenceTemplate:
'{ "lat":<%= latitude %>, "lng":<%= longitude %>, "geofence":"<%= geofence.identifier %>:<%= geofence.action %>" }'
}
});
// Or a compact Array form:
BackgroundGeolocation.ready({
persistence: {
geofenceTemplate:
'[<%= latitude %>, <%= longitude %>, "<%= geofence.identifier %>", "<%= geofence.action %>"]'
}
});
⚠️ Quoting string data
The plugin does not automatically apply double-quotes around string data. Templates are JSON-encoded exactly as written.
Incorrect:
BackgroundGeolocation.ready({
persistence: {
geofenceTemplate: '{"timestamp": <%= timestamp %>}'
}
});
Produces invalid JSON:
{"timestamp": 2018-01-01T12:01:01.123Z}
Correct:
BackgroundGeolocation.ready({
persistence: {
geofenceTemplate: '{"timestamp": "<%= timestamp %>"}'
}
});
{"timestamp": "2018-01-01T12:01:01.123Z"}
Template Tags
Identical to locationTemplate with the following additions:
| Tag | Type | Description |
|---|---|---|
geofence.identifier |
String |
Identifier of the activated geofence |
geofence.action |
String |
"ENTER" or "EXIT" |
latitude |
Float |
|
longitude |
Float |
|
speed |
Float |
Meters |
heading |
Float |
Degrees |
accuracy |
Float |
Meters |
altitude |
Float |
Meters |
altitude_accuracy |
Float |
Meters |
timestamp |
String |
ISO-8601 |
uuid |
String |
Unique ID |
event |
String |
motionchange, geofence, heartbeat, providerchange |
odometer |
Float |
Meters |
activity.type |
String |
still, on_foot, running, on_bicycle, in_vehicle, unknown |
activity.confidence |
Integer |
0–100% |
battery.level |
Float |
0–100% |
battery.is_charging |
Boolean |
Whether device is plugged in |
mock |
Boolean |
True when location was generated from a mock app |
is_moving |
Boolean |
True if recorded while in moving state |
timestampMeta |
Object |
Timestamp metadata; see GeoConfig.enableTimestampMeta |
OptionalmaxMaximum number of days to retain a persisted geolocation record in the plugin’s on-device SQLite database.
When your server fails to return HTTP 200 OK, the SDK will continue retrying uploads according to your HttpConfig settings. If a record remains unuploaded for longer than maxDaysToPersist, it will be permanently discarded to prevent unbounded database growth.
OptionalmaxMaximum number of records the SDK may retain in its on-device SQLite database.
A value of -1 (default) means no limit. When a limit is set and the
number of stored records would exceed this value, the oldest records are
purged to make room for the newest.
See HttpEvent for details on upload behavior.
OptionallocationsSort order for persisted locations.
'ASC' = oldest first; 'DESC' = newest first.
OptionalpersistControls which event types the SDK will persist into its internal SQLite database: locations, geofences, or both.
All recorded events are always delivered to their live callbacks (BackgroundGeolocation.onLocation and BackgroundGeolocation.onGeofence). This option only determines what is written to persistent storage. Events that are not persisted are also not eligible for HTTP uploads via HttpConfig.url.
| Name | Description |
|---|---|
| PersistMode.All | Default — persist both geofence and location events. |
| PersistMode.Location | Persist location events only. |
| PersistMode.Geofence | Persist geofence events only. |
| PersistMode.None | Persist nothing. |
Warning:
This option is intended for specialized cases. For example, if you need
continuous location tracking via BackgroundGeolocation.start but
only want to store geofence events, configure:
persistMode: PersistMode.Geofence.
OptionalextrasOptional arbitrary key/value pairs merged into each recorded location.
These values are persisted and included in all HTTP uploads, making them
ideal for attaching contextual metadata such as user_id, route_id,
or session_id.
See also:
Example:
BackgroundGeolocation.ready({
http: {
url: "https://my-server.com/locations",
params: {
device_id: "abc123" // <-- appended to root JSON of each POST request
}
},
persistence: {
extras: {
route_id: 1234 // <-- merged onto each location record
}
}
});
Incoming request at your server:
POST /locations
{
"device_id": "abc123", // from `params`
"location": {
"coords": {
"latitude": 45.51927004945047,
"longitude": -73.61650072045029
},
"extras": { // from `extras`
"route_id": 1234
}
}
}
OptionaldisableAndroid-only
Disable the automatic insertion of a synthetic “provider-change” location
into the SDK’s SQLite database (and its subsequent HTTP upload).
By default, when an BackgroundGeolocation.onProviderChange event fires, the Android SDK
records a special location documenting when and where the device’s
location-services state changed (e.g., GPS disabled).
This behavior historically existed to support platforms with limited or
unreliable Headless Task implementations (e.g., Cordova, Capacitor).
Some developers have strict server-side JSON schemas or use
locationTemplate, making it impossible to accept the automatically
injected provider field. In these cases, set this flag to true.

Example:
BackgroundGeolocation.ready({
persistence: {
disableProviderChangeRecord: true
}
});
Persistence / Storage Configuration
The PersistenceConfig group controls how the SDK stores, orders, and purges records in its on-device SQLite database. The database acts as a durable buffer between data producers (locations, geofences) and consumers (your app code and the HTTP service).
The SDK prefers an empty database. Each new Location (and geofence event) is written to SQLite immediately, then consumed (and typically deleted) by downstream services such as the HTTP uploader. When a record is successfully processed (e.g., posted to your server), it is removed to keep the buffer small and responsive.
Configure PersistenceConfig via Config.persistence.
What gets stored?
When are records deleted?
A record is deleted when any of the following occur:
20xfor the HTTP upload (see HttpConfig)(oldest records are dropped)
Inspect pending records using:
Ordering
The order in which records are selected for upload or consumption is controlled by locationsOrderDirection:
"ASC"→ oldest first (default)"DESC"→ newest firstJSON templating
Customize the JSON structure of uploaded records:
Templates receive the full record context and can reshape, rename, or nest fields to match backend requirements (see also HttpConfig.rootProperty).
Extras
extras is a free-form key/value map merged into every record when written. Ideal for static context such as
user_id,route_id,appVersion, etc.Persist mode
Control what is written to SQLite with PersistMode:
Example
In this case, the fetched location is persisted (because
persist: true, overriding persistMode), then uploaded immediately if HttpConfig.autoSync is enabled.ProviderChange Records
Disable storage of diagnostic “provider change” records (GPS toggled, settings changed, etc.) with disableProviderChangeRecord to keep the database lean.
Examples
Configure persistence behavior
Inspect and purge the database
Custom JSON templates
Migration from legacy flat Config
Now grouped under PersistenceConfig:
Legacy keys remain but are marked @deprecated. Prefer the compound form going forward.