Setup Guide

Everything you need, in the order you'll actually do it, from creating your account to seeing your first event.

How GeoPulse works

1. You draw a geofence

In the portal, mark a real place on a map and set a radius around it.

2. The SDK watches for it

Your app fires a geofence.enter or geofence.exit event the moment a user crosses that circle.

3. You react to it

Send the event to your own server with a Webhook, or show a banner, message or popup alert right in the app with a Campaign. Either one, or both.

This guide has two parts: set things up in the portal first (no coding), then wire up your app's code. Do them in order, since each part needs something from the one before it.

Key terms

Organization / Project
Your account has one organization. Inside it, a project holds everything for one product: its places, rules and campaigns.
Application
One app (for example your iOS and Android build) that sends events to a project. It has an Application ID and one or more SDK keys.
SDK key
The secret-looking value your app uses to talk to GeoPulse. It ships inside your app, so treat it as an identifier, not a password: if it leaks, revoke it and create a new one. It only works together with its Application ID.
Location / Geofence
A Location is a place on the map. A Geofence is a circle (center and radius) around it that the SDK watches. One location can have several geofences.
Device
One installation of your app. The SDK makes up a random ID for it (not an advertising ID) and registers it when the app starts.
Event
geofence.enter or geofence.exit: a device crossed a geofence. This is the only thing the SDK sends while the user moves around.
Rule + Webhook
A Webhook is a URL on your server. A Rule says which events (and which geofence) should be sent to it.
Experience + Campaign
An Experience is what the user sees in the app. It has a type: an alert (a popup that interrupts), or a banner, card or message (shown inside one of your screens, never as a popup). A Campaign says when to show it: on enter or exit, for which geofence, between which dates, and how often (once per device, every time, or every N hours). A geofence can have up to 5 campaigns, and a phone receives every one that matches.

Part 1: Portal setup

1

Create your account

Portal, no code

Go to the sign-up page and click Continue with Google. Your Google account creates your GeoPulse account the first time, and the same button signs you in afterwards, so there is no password to choose or forget. No credit card, no approval step.

2

Set up your workspace

Portal, no code

Right after signup you'll be asked for an organization name and a project name. Submitting that one form creates all three things you need to get going: the organization, the project, and a starter application called "Playground".

You can create more applications later (one per mobile app you ship) from Projects → your project → Applications.

3

Add a Location and a Geofence

Portal, no code

Open Locations → New location. Search for a place or click the map, give it a name, and save.

Open that location and click New geofence to draw a circle around it. This circle is exactly what the SDK checks against. A user's device entering or leaving it is what creates an event.

Locations page: New geofence button and the geofence list below the map
4

Get your SDK credentials

Portal, no code

Open the SDK page and pick the application you want credentials for (use "Playground" to start). You need two values for your app's code:

  • Application ID: always visible, just copy it.
  • SDK key: click Create SDK key. It's shown once, so copy it immediately and save it somewhere safe. If you lose it, create a new one and revoke the old one.
SDK page: Application ID field and the Create SDK key button

Got your Application ID and SDK key? Now switch to your app's code.

Part 2: Add the SDK

Part 2: Add the SDK to your app

1

Install the package

Code

In your React Native / Expo app (React Native 0.73 or newer):

npm install @damn-coding/geopulse-react-native

That is the only install command. The SDK brings the packages it needs (expo-location, @react-native-async-storage/async-storage and @react-native-community/netinfo) with it. Two cases need one extra step:

  • If npx expo-doctor says one of those packages is not the version your Expo SDK expects, run npx expo install --fix.
  • In a bare React Native app without Expo, run npx install-expo-modules first, because location comes from expo-location. If a native module is reported as missing, add it yourself with npx expo install <package>.
2

Allow location access

Code

The SDK only ever asks for foreground location, never background. Add a usage description to app.json:

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSLocationWhenInUseUsageDescription": "Used to detect nearby places."
      }
    },
    "android": {
      "permissions": [
        "ACCESS_COARSE_LOCATION",
        "ACCESS_FINE_LOCATION"
      ]
    },
    "plugins": [
      [
        "expo-location",
        { "locationWhenInUsePermission": "Used to detect nearby places." }
      ]
    ]
  }
}
3

Initialize the SDK

Code

Use the Application ID and SDK key from Part 1, step 4:

import { GeoPulse } from "@damn-coding/geopulse-react-native";

await GeoPulse.initialize({
  apiKey: "<YOUR_SDK_KEY>",
  applicationId: "<YOUR_APPLICATION_ID>",
});
4

Start it and listen for events

Code
await GeoPulse.start(); // asks for location permission, starts watching

GeoPulse.on("geofence.enter", (event) => {
  console.log("entered", event.geofenceId);
});
GeoPulse.on("geofence.exit", (event) => {
  console.log("exited", event.geofenceId);
});
5

Test it without leaving your desk

Code

In development builds, the SDK runs on a built-in location simulator by default, so no real movement needed:

GeoPulse.simulator.setLocation({ latitude: 33.4484, longitude: -112.074 });

Set it to coordinates inside the geofence you made in Part 1 and you should see geofence.enter fire right away.

Part 3: See it working, and go further

1

Watch the event arrive

Portal, no code

Open Events in the portal. It updates live, and the enter/exit event you just triggered should show up within a few seconds.

2

Check your device registered

Portal, no code

Open Devices. The first successful initialize() call registers the device automatically, and you'll see its platform and SDK version listed.

3

Optional: send events to your own server

Portal, no code

Create a Webhook pointing at your endpoint's URL, then create a Rule that matches an event type (and, if you want, a specific geofence) and sends it to that webhook. Every delivery is signed and retried automatically if your server is down.

4

Optional: show something inside the app

Portal, no code

Build an Experience (an alert, banner, card, or message; only the alert is a popup), then create a Campaign that triggers it on enter or exit for a geofence (or all of them). In your app, listen for it:

GeoPulse.on("experience.received", (payload) => {
  showBanner(payload.experience);
});
5

Keep an eye on things

Portal, no code

Operations shows whether anything failed recently and lists the latest failed and rejected events with the reason. It's the page to check if something seems off.

Portal pages: what each one is for

Every page in the portal, what it's for, and its link. Links to portal pages ask you to log in first if you aren't already. Pages with {id} in the URL are opened by clicking an item in the list above them.

Account pages
  • Sign upClick Continue with Google. Your Google account creates your GeoPulse account the first time, so there is no password to set./signup
  • Log inClick Continue with Google to sign in. It is the same button as sign-up: new accounts are created on first use./login
  • OnboardingShown once after sign-up: name your organization and first project. Creates both, plus a starter application called “Playground”./onboarding

Overview

/dashboard

The home page after you sign in: a snapshot of your workspace.

  • See how many projects, applications, locations and events you have.
  • See a summary of the project currently selected in the top bar.

Setup Guide

/docs

This page. Public, so you can share the link with anyone, no login needed.

  • Follow the setup steps in order.
  • Look up what any portal page is for.

Projects

/projects

A project groups applications, locations, events and everything else. Most pages show data for the project selected in the top bar.

  • Create a project.
  • Open a project to manage its applications and settings.
/projects/{projectId}

Applications tab: create an application per mobile app you ship, and enable or disable it (a disabled application's SDK keys stop working). Settings tab: name, description and status.

Limit: 2 projects per organization, 3 applications per project.

Locations

/locations

Named real-world places. A location on its own does nothing. The geofences inside it are what the SDK checks.

  • Click New location, search for a place or click the map, then save.
/locations/{locationId}

The location's map and its geofences. Click New geofence to draw a circle (name + radius). Edit or delete the location and its geofences here.

Limit: 3 locations per project, 4 geofences per location.

Events

/events

Every geofence.enter and geofence.exit event the SDK has reported, updating live.

  • Filter events, or search for one by its event ID.
  • Click an event to see its details: device, geofence, coordinates, and whether rules and campaigns processed it successfully.

Operations

/operations

What went wrong recently. This is the page to check when something seems off.

  • Is anything wrong: a quick check of whether any events recently failed processing or were rejected before being stored.
  • What failed recently: a table of the latest failed and rejected events, each one clickable for the reason and details.
  • Totals, timings and webhook or campaign activity are not shown here. Use Events to browse everything that was reported.

Devices

/devices

Every device that has run the SDK for this project. Devices register themselves on the first successful initialize(), so there's nothing to add by hand.

  • See each device's platform, SDK version and when it was last seen.
  • Search for a device by its ID (GeoPulse.getDeviceId() in your app).

Rules

/rules

WHEN an event matches, THEN deliver it to a webhook.

  • Create a rule: a name, a trigger (enter or exit), an optional geofence (leave empty for all geofences), and the webhook to send to.
Create a webhook first
Limit: 15 rules per project.

Webhooks

/webhooks

Your own server endpoints that receive events. Every delivery is signed so your server can verify it came from GeoPulse, and failed deliveries are retried automatically.

  • Create a webhook with a name and URL. Its signing secret is shown once, so copy it then.
/webhooks/{webhookId}

Send test to check your endpoint, Regenerate secret if it leaked, and the full delivery history, where you can replay any delivery from there.

Limit: 4 webhooks per project.

Campaigns

/campaigns

WHEN a geofence event matches, THEN show the user an experience inside your app.

  • Create a campaign: name, trigger (enter or exit), optional geofence, the experience to show, and an optional start/end date.
  • Set the frequency so a user isn't shown the same thing too often (e.g. hours between deliveries).
Create an experience first
Limit: 10 campaigns per project.

Experiences

/experiences

The content a campaign shows: an alert (popup), banner, card or message. Content only; your app decides where to draw it. Colors can be typed as a hex code or picked from the color chart.

  • Create an experience: type, title, body, and optional image and call-to-action button (label + URL).
/experiences/{experienceId}/edit

Editor with Data and Style tabs and a live preview.

SDK

/sdk

Where you get the two values your app's code needs.

  • Pick an application and copy its Application ID.
  • Create an SDK key (shown once, so copy it immediately) or revoke an old one.
  • Copy the install and initialize code, pre-filled with your values.
Limit: 3 active SDK keys per application.

Settings

/settings

Account and workspace settings.

  • Profile: your display name.
  • Organization: the organization's name (owner only).
  • Project: the selected project's details.
  • Data & export: download events and delivery history as CSV or JSON before the monthly cleanup deletes them.

SDK and backend basics

Short answers to the things people most often wonder about how the SDK, your app and the GeoPulse backend fit together.

When does the app talk to the backend?
When the app starts (it downloads your geofences and registers the device), when a user enters or leaves a geofence (one small event), to check for a banner or message after such an event, and, while the app is open, once every 15 minutes as a safety check (plus a refresh of your geofences about once an hour). While someone just stands or walks around inside or outside a geofence, nothing is sent. Their location is checked on the phone itself and never uploaded continuously.
What exactly is sent?
For each enter or exit: the coordinates at that moment, the time, which geofence, the device ID, and your Application ID and SDK key. There is no advertising ID, contact list or other personal data from the phone. See the Privacy Policy for the details your app store listing needs.
Does it work when the app is closed or in the background?
No. The SDK only asks for foreground location, so it only detects geofences while your app is open on screen. This is on purpose (it needs no background permission and drains less battery). When the user opens the app again, the next location update is checked as usual.
What if the phone is offline?
Events are saved on the phone first and sent when a connection is back, with growing pauses between tries. The phone keeps up to 100 events and drops any older than 24 hours. If the app starts offline, it uses the last geofences it downloaded.
Why did I not get an event every time I crossed the line?
On purpose: one event per geofence per 2 minutes, at most 3 events a minute from a phone, and an exit only counts once the person is clearly outside (about 20 metres past the edge). That stops GPS wobble at the edge from flooding your project. Very small geofences (under roughly 50 metres) are unreliable for the same reason; use a bigger radius if you can.
Simulator or real GPS?
Development builds use the built-in simulator, so nothing moves unless you call GeoPulse.simulator.setLocation(...). Release builds use real GPS. To try real GPS in a development build, set EXPO_PUBLIC_GEOPULSE_USE_REAL_LOCATION=true in your app's .env.
Is it a problem that the SDK key is inside my app?
No, that is how it is designed: anyone can read it out of an app. What protects you is that events are checked against the geofences you drew, are rate limited, and the key only works with its own Application ID. If a key is misused, revoke it on the SDK page and create a new one (an application can have up to 3 active keys, so you can rotate without downtime).
What are the plan limits?
Per organization 2 projects. Per project: 3 applications, 3 locations, 15 rules, 4 webhooks, 10 campaigns (and at most 5 on any one geofence). Per application 3 active SDK keys, and 4 geofences per location. The backend also limits request rates (for example 30 events a minute and 2,000 a day per application). Your app handles a "too many requests" answer by waiting and retrying, so normal use never notices.
The first request after a quiet period was slow. Is something wrong?
Probably not. The hosted backend is kept awake around the clock, but it can take up to a minute to start again after an update or a restart. The SDK waits up to 15 seconds per request, retries events later if it has to, and uses the last downloaded geofences if the first start cannot reach the server.
How do banners and messages (campaigns) reach the app?
There are no push notifications. After an event that matches a campaign the app is told and fetches the experience straight away. If you change a campaign or experience while someone is inside the location, their open app is updated within a few seconds. Your app listens for experience.received (show or update it) and experience.removed (hide it). See Why changes take a moment for the timings.
How are webhooks delivered?
Each one is signed with your webhook's secret so you can verify it came from GeoPulse, and is sent just after the app gets its answer, so a slow server never delays the phone. If your server is down it is retried with growing pauses (up to 10 tries, and only for 30 minutes; after that the delivery shows as failed with the reason too_old, and you can send it again with Replay on the Webhooks page). Each webhook is also capped (30 a minute, 1,000 a day) to protect your server; anything over that shows as a failed delivery marked rate_limited.

Why changes take a moment

Nothing here is broken when a change is not instant. GeoPulse keeps recent answers in memory for a short time so a busy project does not hit the database on every request, which keeps it fast and keeps your bill small. Waiting is all you need to do, and none of this is a security gap: every request is still checked against your SDK key.

You edit, enable or disable a rule
Up to 3.5 minutes for new events: the server remembers a project's rules for 3.5 minutes. A rule you just disabled can still fire for a few more events during that time.
You edit a webhook (address, enabled, secret)
Applies to the next delivery.
You create, edit, enable, disable or delete a campaign
Applies to anyone who enters or leaves afterwards straight away. People already inside the location are updated too: within a few seconds if their app is open (it is told right away), and at the latest within 15 minutes.
You edit an experience (title, text, image, button, style)
Phones that are inside the location and already showed it get the new version within a few seconds. Phones that have not shown it yet get the new version when they do.
You delete or disable a campaign people are looking at
It is removed from the screen of people still inside, within a few seconds (the app receives experience.removed).
You add, move, resize, disable or delete a geofence
Events are checked against the new geofence within about 30 seconds. The list given to phones refreshes within 3.5 minutes, and a phone re-reads it about once an hour while the app is open, and every time it is launched.
You revoke an SDK key or disable an application
Up to about a minute on the server. The app stops sending once it is refused, and stops completely within about an hour or at its next launch.

Good to know

  • A phone sends at most one event per geofence every 2 minutes, and at most 3 events a minute overall. Walking in and out repeatedly, or standing on the edge where GPS wobbles, does not flood your project. Leaving only counts once the person is clearly outside (about 20 metres past the edge).
  • A campaign you schedule for a later start is not given to people already inside; it applies to anyone who enters once it is active.
  • An experience that has been waiting for a phone for more than a day is dropped, so nobody sees a stale welcome after being offline.
  • Updates to people already inside need their app open (location is foreground-only). If their connection drops, the app catches up on its next check.

Your data: monthly cleanup and export

Events and delivery history are temporary. At the start of every month (00:00 UTC) GeoPulse deletes everything created before that moment, so each month starts fresh and the database stays small. It happens automatically: the cleanup runs the first time the backend is awake after the 1st, which is normally within the hour. For the last 7 days of the month a banner at the top of the portal reminds you, and it turns red in the final 24 hours.

Deleted every month
Events, webhook deliveries, rejected events, device presence, and campaign deliveries from campaigns set to show every time or after a gap.
Never deleted
Your projects, locations, geofences, rules, webhooks, campaigns, experiences, applications and SDK keys. Deliveries from campaigns set to show once per device are also kept, so nobody sees the same message twice.
How to keep a copy
Open Settings → Data & export. Pick the project, what to export (events, webhook deliveries, campaign deliveries or rejected events), a date range and CSV or JSON, then click Download. Dates are in UTC.
Limit per download
The newest 10,000 rows. If a range has more, narrow the dates and download again. Each row read counts toward the database's free daily allowance, so very large exports are best split over days.

Download what you need before the 1st: once the cleanup has run, deleted data cannot be recovered. Open Settings and choose the Data & export tab.

Troubleshooting

"apiKey and applicationId required" error
Double check the two values you copied from the SDK page. One of them is empty or mistyped.
No geofence.enter ever fires
Make sure a geofence actually exists for this application's project under Locations, and that GeoPulse.getConfiguredGeofences() isn't empty.
"This application has been disabled" error
Someone disabled the application under Projects → your project. Re-enable it, or use a different application's credentials.
initialize() fails with a network error
Your app can't reach the backend URL. If you're pointing at a local server from a physical phone, use your computer's LAN IP, not localhost.
You can't find your event in the portal
Check the project selected in the top bar matches the one your SDK key's application belongs to.
Works in the simulator but nothing happens on a real phone
Development builds use the simulator unless you set EXPO_PUBLIC_GEOPULSE_USE_REAL_LOCATION=true. Also check the user allowed location, the app is open on screen (there is no background tracking), and the geofence radius is not tiny.
Fewer events than expected when walking in and out
Expected: one event per geofence per 2 minutes and at most 3 a minute, and an exit only counts about 20 metres past the edge. See SDK and backend basics.
My banner or message never appears
Check the campaign is enabled and inside its dates, it targets the right event type (enter or exit) and geofence, and its frequency is not "once" for a device that already received it. In your app, register GeoPulse.on("experience.received", ...) before calling start(), and make sure the device shows up under Devices.
Events or banners arrive late, or the SDK logs a rate-limit (429) message
The backend limits request rates (for example 30 events a minute and 2,000 a day per application) and the SDK waits and retries automatically. If it keeps happening, look for an app that sends a lot of events, or check Operations for failures.
A change I made in the portal is not showing yet
Most changes apply within 3.5 minutes; geofences reach already-running apps within about an hour. See Why changes take a moment.
The first start is slow or fails once, then works
The hosted backend can take up to a minute to start again after an update or a restart. The SDK retries and uses the last downloaded geofences, so just start it again.
npm install reports a version conflict, or Expo says a package version is wrong
The SDK needs React Native 0.73 or newer. For a version mismatch run npx expo install --fix; for a bare React Native app run npx install-expo-modules first.

Still stuck? Reach out to the GeoPulse team.