/ activity

Automate travel reimbursements in your app within minutes

When I started my career as a management consultant, I was introduced to the idea of filing travel reimbursements. It meant keeping all my cab bills safe and budgeting a couple of hours at the end of the month to compile them together. Now I know how this can be automated, albeit only a couple of years too late.

Apps such as MileIQ have changed how travel reimbursements are filed by people on the move. Users don't need to start or stop their trips. The sensors on the phone can tell when the user is moving or stopped. The app uses that to get locations while on the move and meter the trip.

With HyperTrack, you can build automatic travel reimbursements in your own app within minutes. This tutorial will show you how!

What are we building

Let's take a look at how MileIQ works. The main view shows a list of trip cards with the distance, time and locations of travel. These trip cards are created automatically using the location and activity sensors on the device.

In this tutorial, we will recreate these trip cards in Swift, using the HyperTrack SDK. Let's start a new project in Xcode and jump right in.

Step 1: Integrate SDK

Integrating the HyperTrack iOS SDK is the first step. The SDK is hosted on Cocoapods, and you can set it up by editing your project's Podfile.

use_frameworks!

target 'AppName' do
   pod 'HyperTrack'
end

To use the SDK, you will need an API key: sign up on HyperTrack to get your key. In your AppDelegate file, use the API key in the SDK initialize method. Run the app to ensure everything is working.

import HyperTrack

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions
                     launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
         HyperTrack.initialize("YOUR_KEY")
        
        return true
    }
}

Step 2: Enable location and activity

The SDK needs requisite permissions to access the user's location and activity in the background. Select the following capabilities for your app.

Capabilities

The SDK has helper methods to show prompts to enable location and activity permissions. To use these, you will need to define info strings for the keys given below. These strings will be shown to the user in the prompt.

HyperTrack.requestAlwaysAuthorization()
HyperTrack.requestMotionAuthorization()
Key
Privacy - Motion Usage Description
Privacy - Location When In Use Usage Description
Privacy - Location Always and When In Use Usage Description

Step 3: Start tracking

With the basic configuration in place, we can interact with HyperTrack primitives to build our app. We will use the user primitive to identify the app user.

In your app's login flow, we will call the HyperTrack method to create the user object. The name of the user and other identifiers can be passed as parameters. Once the call goes through successfully, we will start tracking the user.
class ViewController: UIViewController {
    @IBAction func loginButton(_ sender: Any) {
        HyperTrack.getOrCreateUser("Arjun",
                                   _phone: "",
                                   "arjun@example.com") { (user, error) in
            if (error == nil) {
                HyperTrack.startTracking()
            }
        }
    }
}

Step 4: Detect trip start

Now that we are tracking for location and activity in the background, we can setup a listener to detect when the user starts moving. We will set a HyperTrack delegate, which will listen for specific events.

The HyperTrackEventType.stopEnded will inform us when a user's stop ends and the user starts moving. We will create an action when this happens. An action is a HyperTrack primitive to annotate what the user is doing. In this case, we are representing a user's trip with an action.

class AppDelegate: UIResponder, UIApplicationDelegate, HyperTrackDelegate {
    func didReceiveEvent(_ event: HyperTrackEvent) {
        if event.eventType == HyperTrackEventType.stopEnded {
            let htActionParams = HyperTrackActionParams()
            
            HyperTrack.createAndAssignAction(htActionParams, { (action, error) in
                if let action = action {
                    // Action successfully created
                    UserDefaults.standard.set(action.id!, forKey: "HyperTrack-Action-ID")
                }
            })
        }
    }
}

Once an action is created, we will save the action id into UserDefaults to use it in our ViewController.

Step 5: Show live trip

Now that we have an action, we can track it. Let's create a card where we can embed a map view of the action.
class TripsViewController: UIViewController, HTViewCustomizationDelegate {
    
    @IBOutlet weak var mapView: UIView!
    let actionKey = "HyperTrack-Action-ID"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view, typically from a nib.
        let actionId = UserDefaults.standard.string(forKey: actionKey)
        
        if let actionId = actionId {
            let hyperTrackMap = HyperTrack.map()
            hyperTrackMap.setHTViewCustomizationDelegate(customizationDelegate: self)
            hyperTrackMap.embedIn(mapView)
            
            HyperTrack.trackActionFor(actionID: actionId)  
        }
    }
}

Step 6: Detect trip end

Just as the HyperTrack SDK can tell us when a trip starts, it can detect when a trip ends. The event we need to look at is HyperTrackEventType.stopStarted. We will mark the ongoing action as completed when this event triggers.

class AppDelegate: UIResponder, UIApplicationDelegate, HyperTrackDelegate {
    func didReceiveEvent(_ event: HyperTrackEvent) {
        if event.eventType == HyperTrackEventType.stopStarted {
            let actionId = UserDefaults.standard.string(forKey: "HyperTrack-Action-ID")
            
            if let actionId = actionId {
                HyperTrack.completeAction(actionId)
            }
        }
    }
}

Step 7: Measure distance

We can display the distance covered and other properties of the action in the trip card. To achieve this, set up a delegate that pushes action data updates to our ViewController.

When the action completes, the trip card shows the action polyline and the final distance traveled. You can send these values to your backend server to aggregate reimbursement data.
class TripsViewController: UIViewController, HTEventsDelegate {
    @IBOutlet weak var startAddress: UILabel!
    @IBOutlet weak var endAddress: UILabel!
    @IBOutlet weak var distance: UILabel!

    func didRefreshData(forAction: HyperTrackAction){
        let statusInfo = forAction.getStatusCardInfo()
        distance.text = "\(statusInfo.distanceCovered) mi"
        startAddress.text = statusInfo.startAddress
        endAddress.text = statusInfo.completeAddress   
    }
    
    override func viewDidAppear() {
        super.viewDidAppear()
        // setup HyperTrack event delegate 
        HyperTrack.setEventsDelegate(eventDelegate: self)
    }
}

Conclusion

With location and activity, the HyperTrack SDK can automate distance measurements. The data is available via simple API calls that you can send to expense management apps like Expensify or Concur.

Furthermore, your app users can send a live tracking link to customers so you can reduce wait times. You may integrate this with your salesforce automation backend to snap a visited location to a customer destination and attach the trip to the customer in the system. This way, your customer relationship history can show relevant trip information, making it easier for the expense approver as well.


Developers around the world have built automated travel reimbursements for their internal teams using HyperTrack. With location and activity, our SDK automates reimbursements, so that users can forever free their minds from the hassle of logging trips. Sign up to get started!