The most important piece of advice we give when starting your beaconified app development journey is to start by asking yourself: what’s the actual user experience going to look like, and how does it benefit the users of your app? Find an answer to these two questions and you can’t go wrong. Today, however, we want to talk about something a tad different: what’s in it for you! Besides a smoother end-user experience in your app, (e.g., not having to punch numbers into the audio guide anymore), which translates to more downloads, there’s a more tangible, immediate benefit from having beacons deployed in your venue and your app equipped with the Estimote SDK: real-world analytics. Today’s update brings improved functionality across the board. Learn what’s new, how to integrate it with your app and how to access the information via our RESTful API.
The iterative approach
We launched the first version of our analytics last year, but the iBeacon market has matured a lot since then—so it was time for an update. With more and more beacons moving out of the proverbial garages of early adopters, and into actual venues, we’ve been gathering a lot of feedback. With a community of 40,000 developers and growing, that’s our release cadence: move fast, put an early version in the hands of our community, listen to your thoughts, ship improvements.
Regions instead of beacons
We’ve redesigned how we gather analytics data so that you’re no longer constrained to individual beacons—which is super useful when you’re working with more than 20 beacons. Because iOS limits the number of beacon regions you can monitor at any given time to 20, sometimes you simply need to group your beacons—instead of creating one region per beacon, which would limit you to 20 beacons.
Let’s say we’re in a museum and there’s this one big hall with a t-rex exposition. Since it’s a big space (the tyrannosaurus wasn’t a small creature), you installed 10 beacons in there to cover its entirety, and assigned them a single major to group them into a single region. Previously, if you wanted to enable analytics for these beacons you’d have to do it on a per-beacon basis:
ESTCloudManager.setupAppID("YOUR_APP_ID", andAppToken: "YOUR_APP_TOKEN")
ESTCloudManager.enableMonitoringAnalytics(true)
for i in 1...10 {
let beaconRegion = CLBeaconRegion(
proximityUUID: NSUUID(UUIDString: "YOUR_UUID")!,
major: 13, minor: CLBeaconMinorValue(i),
identifier: "t-rex, beacon \(i)")
self.beaconManager.startMonitoringForRegion(beaconRegion)
}
Now, you can simply do …
ESTCloudManager.setupAppID("YOUR_APP_ID", andAppToken: "YOUR_APP_TOKEN")
ESTCloudManager.enableMonitoringAnalytics(true)
let beaconRegion = CLBeaconRegion(
proximityUUID: NSUUID(UUIDString: "YOUR_UUID")!,
major: 13, identifier: "t-rex, all beacons")
self.beaconManager.startMonitoringForRegion(beaconRegion)
… and we’ll keep track of how many people with the museum app installed enter and exit the hall. Of course, you’re still free to stick to more specific regions, but just keep the 20-region limit in mind.
There’s one important implication of us moving from per-beacon to per-region analytics: previously, if you changed your beacon’s UUID, major or minor after it already gathered some analytics data, the data would stay with the beacon. Now, since that data is tied to regions instead of beacons, that data will stay with the previous UUID, major and minor.
New RESTful API endpoints for analytics
Naturally, the analytics themselves are only as useful as the information you can extract from them. So we’ve expanded the analytics endpoints of our Estimote Cloud RESTful API with more high-level reporting in mind. Until now, we gave you access to a daily pings count for a beacon—a ping being somebody entering the range of a beacon. It’s a great metric to quickly assess traffic trends inside a certain area, but apart from that it didn’t provide much more insight. That’s why you can now access two additional endpoints: visits and unique visitors.
Imagine you own a restaurant and one of your patrons is sitting at a table and enjoying her t-rex steak (we’re sure that’s a thing!). While she sits and eats her meal, she remains in range of your beacon. A single ping was registered when she entered the room. But her phone rings, and she goes outside to take the call—coming back, that’s the second ping. Visit to the restroom? A third ping. Clearly, not an ideal metric if you as the owner want to measure the actual traffic in the venue. That’s where the visits endpoint comes in. As long as the pings are spread apart no further than 60 minutes, we’ll group them into a single visit. Suddenly, the patron’s short absence at the table no longer affects the analytics data. And if she came in for lunch and then comes back in the evening (who wouldn’t want to frequent a restaurant with t-rex steaks?), Estimote Cloud will count that as two distinct visits.
Setting all of this up is really easy. In your app’s code, add:
ESTCloudManager.setupAppID("YOUR_APP_ID", andAppToken: "YOUR_APP_TOKEN")
ESTCloudManager.enableMonitoringAnalytics(true)
let uuid = NSUUID(UUIDString: "YOUR_UUID")!
let entireRestaurant = CLBeaconRegion(
proximityUUID: uuid, identifier: "beacons in the entire restaurant")
self.beaconManager.startMonitoringForRegion(entireRestaurant)
let room1 = CLBeaconRegion(proximityUUID: uuid,
major: 1, identifier: "beacons in room 1")
self.beaconManager.startMonitoringForRegion(room1)
let room2 = CLBeaconRegion(proximityUUID: uuid,
major: 2, identifier: "beacons in room 2")
self.beaconManager.startMonitoringForRegion(room2)
And then you can access the data like this:
curl -u <WEB_APP_ID>:<WEB_APP_TOKEN> -H 'Accept: application/json' \
https://cloud.estimote.com/v1/analytics/<YOUR_UUID>:1/visits?↩
↪resolution=daily
# example response:
{
"region": "<YOUR_UUID>:1",
"unique_visits": [{
"time": "2014-04-01T12:00:00",
"app_in_foreground_visits": 34,
"app_in_background_visits": 53,
"total_visits": 86
}, {
"time": "2014-04-02T12:00:00",
"app_in_foreground_visits": 41,
"app_in_background_visits": 38,
"total_visits": 79
}, {
…
}],
"timezone": "America/New_York"
}
Continuing the restaurant example above, here you can see that on the 04/01 there were 86 visits to room 1 of your restaurant and on 04/02 there were 79. We also give you a breakdown of how many of these visits happened with your app entirely in the background (app_in_background_visits
) or if the user has opened your app at least once throughout the visit (app_in_foreground_visits
).
But wait, there’s more! You can now customize the time period you’re interested in (the from
and to
parameters, defaults to “one week ago till now”), and also decide whether you want the data grouped by days or hours (the resolution
parameter, defaults to “hourly”). Say this time you’re interested in how many unique visitors came in during lunch hours on April 1st:
curl -u <WEB_APP_ID>:<WEB_APP_TOKEN> -H 'Accept: application/json' \
https://cloud.estimote.com/v1/analytics/<YOUR_UUID>/unique_visitors?↩
↪from=2015-04-01T11:00-05:00&to=2015-04-01T14:00-05:00&resolution=hourly
# example response:
{
"region": "<YOUR_UUID>",
"unique_visitors": [{
"time": "2014-05-01T11:00:00",
"app_in_foreground_visitors": 8,
"app_in_background_visitors": 6,
"total_visitors": 14
}, {
"time": "2014-05-02T12:00:00",
"app_in_foreground_visitors": 16,
"app_in_background_visitors": 23,
"total_visitors": 39
}, {
…
}],
"timezone": "America/New_York"
}
How do we understand a unique visitor? The Estimote SDK generates a unique, anonymized identifier whenever a user installs and runs your app for the first time. We then send this identifier with every single analytics event (such as somebody entering the range of a beacon). When you request the unique visitors data for a certain timespan, we’ll check how many unique identifiers came in with all the events within that period, and present it to you.
Monitoring AND ranging
The final improvement to Estimote’s analytics which we’re really excited about: you can now gather data not just from monitoring events (i.e., enters and exits), but also ranging. Since ranging beacons gives very detailed information about every single beacon detected nearby, and is not limited in any way (like monitoring), this allows much more fine-grained data collection.
Coming back to the museum example: you’re now gathering analytics for the whole “t-rex” region of 10 beacons—which enables you to save 9 monitoring slots for other regions—but maybe you’re still interested in getting data from individual beacons when the app is in the foreground and can range beacons without limits. Well, as long as you have analytics enabled in the Estimote SDK, that’s exactly what will happen!
ESTCloudManager.enableRangingAnalytics(true) // *NEW*
let beaconRegion = CLBeaconRegion(
proximityUUID: NSUUID(UUIDString: "YOUR_UUID")!,
major: 13, identifier: "t-rex")
self.beaconManager.startMonitoringForRegion(beaconRegion)
self.beaconManager.startRangingBeaconsInRegion(beaconRegion) // *NEW*
…
# data from monitoring, the whole "t-rex" region
curl -u <WEB_APP_ID>:<WEB_APP_TOKEN> -H 'Accept: application/json' \
https://cloud.estimote.com/v1/analytics/<YOUR_UUID>:13/visits
# data from ranging, an individual beacon (minor: 1) in the "t-rex" region
curl -u <WEB_APP_ID>:<WEB_APP_TOKEN> -H 'Accept: application/json' \
https://cloud.estimote.com/v1/analytics/<YOUR_UUID>:13:1/visits
Voilà! You deserve a solid t-rex steak now.
And remember, even as these new beacon analytics tools continue to get more powerful, never compromise having a strong bias toward the end consumer value.
More to come
The update to the Estimote’s analytics is ready today—go try it out! (Hint: as with the first version, analytics works with Secure UUID beacons too.) We’re eagerly looking forward to hearing your thoughts, so that we can continue to iterate. What kind of API endpoints would you like to see next? Any additional filters that would come in handy? How do you anticipate using the data from the real-world analytics to optimize your venue? Make sure to let us know—on our forums, Twitter, or simply drop us an email.
Enjoy the number-crunching!
Piotr Krawiec, Technology Evangelist at Estimote