Smartwhere Integration


The TUNE Marketing Console integration with Smartwhere provides clients with location-based business intelligence by implementing defined geofences to provide insights on "in-store" user engagement for their mobile app.

For more information on what you can do with the Smartwhere integration and how to enable the integration, please see our Smartwhere Integration - In-Store Event Tracking article.

Integration Requirements

  • The integration of the TUNE SDK in your mobile app:
    • Android 4.9.0+
    • iOS 4.11.0+
  • The integration of the Smartwhere SDK in your mobile app.
    • Android - already present in existing build.gradle snippet below
    • iOS - Download here
  • Collect GPS latitude and longitude on app open.
    • Request the end-user permission for geo-location access, at the earliest appropriate instance in your app flow. This will allow the SmartWhere SDK to handle geofence transitions and also allow (latitude, longitude) to be collected when Tune measureSession/measureEvent methods are called.
  • Minimum platform versions:
    • Android - API 18 : Android 4.3 (Jelly Bean)
    • iOS - 7.0


Android Sample Implementation

    1. In addition to the changes required for Tune, include the following dependencies in your App module build.gradle:
      compile ''
      compile 'com.smartwhere:android-tune:16364'
    2. AndroidManifest.xml -- same as the ones for Tune Android -- no SmartWhere specific changes.
    3. Add the following in the MainActivity onCreate().
      // REQUIRED: request location access permission
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 102);
      // REQUIRED: initialize Tune
      Tune.init(this, advertiserId, conversionKey, false);
      // OPTIONAL: set a Tune listener
      Tune.getInstance().setListener(new TuneListener() {


iOS Sample Implementation

CLLocationManager initialized in UIAppDelegate.applicationDidFinishLaunching: before Tune.init is called:

@import AdSupport;
@import CoreBluetooth;
@import CoreLocation;
@import CoreSpotlight;
@import CoreTelephony;
@import Tune;
@import MobileCoreServices;
@import iAd;
@import Security;
@import StoreKit;
@import SystemConfiguration;

@interface AppDelegate () <TuneDelegate, CLLocationManagerDelegate> {
    CLLocationManager *locationManager;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    // REQUIRED: request location access permission here or at some other location in your code
    locationManager = [CLLocationManager new];
    //locationManager.delegate = self;
    [locationManager requestAlwaysAuthorization];
    [locationManager startUpdatingLocation];

    // REQUIRED: initialize Tune
    [Tune initializeWithTuneAdvertiserId:TUNE_ADVERTISER_ID

    // OPTIONAL: set a delegate for Tune (and implement the TuneDelegate protocol)
    [Tune setDelegate:self];
    return YES;


Please make sure of the following during SDK implementation:

  • SmartWhere framework - iOS system frameworks dependency requires CoreBluetooth and CoreLocation frameworks.
  • Request the end-user permission for geo-location access, at the earliest appropriate instance in your app flow. This allows the SmartWhere SDK to handle geofence transitions and also allows (latitude, longitude) to be collected when TUNE measureSession/measureEvent methods are called.
  • Please make sure that NSLocationAlwaysUsageDescription, i.e. "Privacy - Location Always Usage Description" entry exists in the Info.plist. The value of this key should include a user-visible message about why your app needs to access the user's geo-location, e.g. "Please allow geo-location access to get location based offers!"

Supporting Proximity Events

For any account that wishes to support proximity events can add the following code in the application delegate.

Objective-C Example

/* add variable to hold the last proximity notification.  Example adding variables to the implementation;*/
@implementation AppDelegate {
    SWNotification * _lastEvent;
    SWAction * action;
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    SmartWhere* smartWhere = [[TuneSmartWhereHelper getInstance] getSmartWhere];
     if (smartWhere) {
        SWNotification* swNotification = [smartWhere didReceiceLocalNotification:notification];
        if (swNotification) {
            [self smartWhere:smartWhere didReceiveLocalNotification:swNotification];
/* This second method will receive the proximity notification and display a standard UIAlertController
    Alternatively, you can modify this code or handle the notification in some other fashion (i.e. listview), refer to documentation on parsing proximity notifications */
- (void)smartWhere:(SmartWhere *)smartwhere didReceiveLocalNotification:(SWNotification *)notification {
    NSLog(@"SWNotification came in while in the foreground, alerting the user");
    _lastEvent = notification;
    /* display notification with a simple UIAlertController */
    UIAlertController *alertcontroller = [UIAlertController alertControllerWithTitle: notification.title
                                                                             message: notification.message
                                                                      preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction *okAction = [UIAlertAction actionWithTitle: @"Ok"
                                                       style: UIAlertActionStyleDefault
                                                     handler: ^(UIAlertAction *action) {                                                         
                                                         [smartwhere fireLocalNotificationAction:_lastEvent];
                                                         _lastEvent = nil;                                                     
    [alertcontroller addAction: okAction];
    UIAlertAction *cancel = [UIAlertAction actionWithTitle: @"Cancel" style: UIAlertActionStyleDestructive handler: nil];
    [alertcontroller addAction: cancel];
    UINavigationController *navigationController = (UINavigationController *) self.window.rootViewController;
    [self.window setRootViewController:navigationController];
    [navigationController presentViewController:alertcontroller animated:YES completion:nil];

Common Success/Errors Responses

When debugMode is enabled, console log statements similar to the following might show up:

com.tune.sw_tune_android I/ProximitySDK: ProximityService version: REL_16364
com.tune.sw_tune_android I/ProximitySDK: ConfigurationHandler: Reading Proximity Configuration class com.tune.sw_
com.tune.sw_tune_android I/ProximitySDK: Defaulting persisted config.
com.tune.sw_tune_android I/ProximitySDK: ProximityService Stopping!  Credentials are not set
com.tune.sw_tune_android I/ProximitySDK: Defaulting SWCreds
com.tune.sw_tune_android I/ProximitySDK: Defaulting persisted config.
com.tune.sw_tune_android I/ProximitySDK: Config Command received
com.tune.sw_tune_android I/ProximitySDK: GeofenceServerRunner - starting.
com.tune.sw_tune_android I/ProximitySDK: GeofenceServerRunner - got 3 fences.
com.tune.sw_tune_android I/ProximitySDK: GeofenceServerRunner - adding 3 fences.
com.tune.sw_tune_android D/ProximitySDK: GeofenceServerRunner - rescheduling geofence update in 86400000
com.tune.sw_tune_android I/ProximitySDK: (geofence-transition) received geofence event id=0
com.tune.sw_tune_android I/ProximitySDK: handleGeofenceTranstionIntent: Received GEOFENCE_TRANSITION_ENTER from google for 1032545 handling enter.
com.tune.sw_tune_android I/ProximitySDK: geofence-transition: Entered fence 1032545 but needs update...
com.tune.sw_tune_android I/ProximitySDK: Transition 1032545 Eiffel Tower withTrigger 20
com.tune.sw_tune_android I/ProximitySDK: mTriggerFenceDiscovery - starting.



sw_tune_2[33005:3181625] TUNE SDK - [TuneSmartWhereHelper.m:65] - WARN - TUNE: Starting SmartWhere Proximity Monitoring
sw_tune_2[33005:3181625] ProximityService version: REL_16354
sw_tune_2[33005:3181625] configWithDictionary start
sw_tune_2[33005:3181625] configWithDictionary complete
sw_tune_2[33005:3181625] getLocationManager: startMonitoringSignificantLocationChanges
sw_tune_2[33005:3181625] serverOverrides start
sw_tune_2[33005:3181625] serverOverrides complete
sw_tune_2[33005:3181625] Setting DEBUG_LOGGING to YES...
sw_tune_2[33005:3181625] Got 877 beacons: (
sw_tune_2[33005:3181625] Setting RANGE_IN_ENTER_THRESHOLD to 1
sw_tune_2[33005:3181625] Setting RANGE_INSIDE_EXIT_THRESHOLD to 1
sw_tune_2[33005:3181625] Beacons ready for monitoring
sw_tune_2[33005:3181625] Starting location manager.  Monitoring: {(
sw_tune_2[33005:3181625] Start watching beacon: 2f236764-cf8f-4ab1-cdf5-f4933ba9eea8
sw_tune_2[33005:3181625] WARNING: Ranging beacons is not available
sw_tune_2[33005:3181625] getFencesForLocation: Got 6 fences for application 877
sw_tune_2[33005:3181625] getFencesForLocation: Watched fences doesn't exist yet.
sw_tune_2[33005:3181625] startWatchingFences: Start watching fence: 1032543 Sydney 7K <-33.868820,151.208268,7000.000000>
sw_tune_2[33005:3181625] startWatchingFences: Start watching fence: 0 Refresh Geofence <-33.863400,151.211000,5000.000000>
sw_tune_2[33005:3181625] SWEventsObject: enter: Created visit id 74C7A139-0FFF-4612-8612-93A9B0A50327 for 1032543
sw_tune_2[33005:3181625] addTrackingObject type 5 for item 1032543 with trigger 20
sw_tune_2[33005:3181625] Sending local notification Sydney 7K Entered
Entered event
sw_tune_2[33005:3181625] addTrackingObject type 2 for item 1032543 with trigger 20
sw_tune_2[33005:3181625] didUpdateLocations: stopUpdatingLocation


Troubleshooting Common Issues

  • iOS: Make sure CoreLocation and CoreBluetooth frameworks are included.
  • Android: Make sure AndroidManifest.xml includes uses-permission tag for ACCESS_FINE_LOCATION
  • Android: Make sure build.gradle includes compile entry for gms:play-services-location
  • Android: Make sure location permission is being requested -- e.g. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 102);
  • Make sure location access permission is granted when the dialog shows up. This permission can also be modified from the system Settings.
  • Make sure appropriate geofences, beacons, etc. have been setup on SmartWhere.
  • Check the TUNE TMC AA dashboard "Test Logs" report since this report can show near real time log records.
Have a Question? Please contact for technical support.