Smartwhere Integration

main-logo

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 for the benefits of proximity.

Important Note: If you already have downloaded the TUNE SDK, follow these instructions to integrate Smartwhere and DO NOT download the combined Framework from TUNE’s Github repo or from within the TUNE Marketing Console dashboard.

iOS Integration

iOS Requirements

  • Integrate the combined TUNE<>Smartwhere SDK in your mobile app:
    • Download the combined Framework from Github here, or
    • Reference Framework in your Podfile:
      # Pods for TuneSmartwhereSDK
      pod 'Tune', :git => 'https://github.com/smartwhere/tune-ios-sdk.git', :tag => '4.12.4'
    • Follow TUNE iOS Quick Start Instructions here substituting the combined framework or Podfile reference
  • If Manually including the combined Framework then add the following additional frameworks to your project:
    • CoreLocation.framework
  • 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:
    • iOS - 7.0

iOS Sample Implementation

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

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

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

@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
                       tuneConversionKey:TUNE_CONVERSION_KEY
                         tunePackageName:TUNE_PACKAGE_NAME
                                wearable:NO];

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

    return YES;
}

@end

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];
}

iOS Common Success/Error Responses

When debugMode is enabled, console log statements similar to the following may appear:

sw_tune_2[33005:3181625] TUNE SDK - [TuneSmartWhereHelper.m:65] - WARN - TUNE: Starting SmartWhere Proximity Monitoring
sw_tune_2[33005:3181625] ProximityService version: REL_17087.1
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: (
    "2f236764-cf8f-4ab1-cdf5-f4933ba9eea8"
)
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
...

iOS Troubleshooting Common Issues

  • Make sure CoreLocation and CoreBluetooth frameworks are included.
  • 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.

Android Integration

Android Requirements

  • Integrate the TUNE SDK in your mobile app following the Android Quick Start instructions here:
    • Note: The minimum TUNE Android SDK Version is 4.9.0+
  • Integrate the Smartwhere SDK in your mobile app.
    • Refer to build.gradle snippet below
  • 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)

Android Sample Implementation

    1. In addition to the changes required for TUNE, include the following dependencies in your App module build.gradle:
      compile 'com.google.android.gms:play-services-location:10.0.1'
      compile 'com.smartwhere:android-tune:17087.1'
      
    2. AndroidManifest.xml -- same as the ones for TUNE Android -- no SmartWhere specific changes.
    3. Add the following in the MainActivity onCreate().
      // REQUIRED: initialize Tune
      Tune.init(this, advertiserId, conversionKey, true);
      Tune.getInstance().setPackageName(packageName);
      
      // OPTIONAL: set a Tune listener
      Tune.getInstance().setListener(new TuneListener() {
          ...
          ....
      });
      // REQUIRED FOR ANDOID 6.0+: request location access permission at appropriate point in your application
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, CALLBACK_RETURN_CODE);

ProGuard for Android Integration

If using ProGuard, exclude the Smartwhere classes from obfuscation in your ProGuard configuration file with the following lines:

-keep class com.proximity.library.** { public protected private *; }

Android Common Success/Error Responses

When debugMode is enabled, console log statements similar to the following may appear:

com.tune.sw_tune_android I/ProximitySDK: ProximityService version: REL_17087.1
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.
...

Android Troubleshooting Common Issues

  • 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 support@tune.com for technical support.