BitLabs iOS SDK

This page will guide you through the integration of our iOS SDK into your app.

CHANGELOG

To check the latest version and all the previous ones of the SDK, you can check this page.

What's new in this page:

Since v3.1.0

Account Set-Up and retrieving your API Key

Before we can get started with implementing the SDK, you should retrieve your API Key for your integration from the BitLabs Dashboard. If you haven't created an account yet, you can do so here and follow the instructions for the dashboard starting with Sign up & Set up.

Adding the SDK

Add a Podfile with BitLabs framework as a pod reference.

# Installing the SDK as pod reference
# You can specify the version you want or just add 'BitLabs' for the latest version 
pod 'BitLabs', '~> 3.0.1'

Configuring the SDK

You must configure the SDK before you can use it. You can do so with the following code.

BitLabs.shared.configure(token: "YOUR_TOKEN", uid: "YOUR_USER_ID")

This is where you will need the API key from the dashboard, as you will need to replace "YOUR-TOKEN" with it. For "YOUR-USER-ID", you will need to dynamically insert the user id for each app user. Make sure the id used here is unique and that it does not change, as the user's profile will be stored under this id.

πŸ“˜

You can also hold the reference of BitLabs.shared in a global or local variable like this:

let bitLabs = BitLabs.shared

And now you can use the library as

bitLabs.configure(token: "YOUR_TOKEN", uid: "YOUR_USER_ID")

Using the SDK

Show BitLabs to the user

Now it's time to use the BitLabs SDK so that your users can start taking surveys. Call the .launchOfferWall(parent:) function to open the Offer Wall/Direct Link. BitLabs will show up and the user will see qualifications or surveys.

BitLabs.shared.launchOfferWall(parent: <UIViewController>)

The parent is a <UIViewController> used to present the WebView of the Offer Wall.

🚧

Note

Upon closing the Offer Wall(i.e. the WebView), several Assertion Errors might be printed into the console. These errors seem to be caused by some background process from iOS trying to communicate with the closed WebView and we can't control iOS. As per our testing, these errors do not have any practical effect on the library. So you can ignore them.

For more info check this StackOverflow Answer.

πŸ‘

That's it!

Theoretically, this is all you have to do. Anything below is optional but can improve the user experience.

Check For Surveys - Check if there's something to do for the user

You can use .checkSurveys(completionHandler:) to check if a survey is available for the user. On Success, the callback function returns true whenever there's at least one survey or qualification question available for the user. Otherwise, it returns false. On Failure, it returns an error where you can check the reason.

 BitLabs.shared.checkSurveys { result in
	switch result {
	case .failure(let error):
		print("[Example] Check For Surveys \(error)")
    
	case .success(let hasSurveys):
		print("[Example] \(hasSurveys ? "Surveys Available!":"No Surveys Available!")")
	}
}

Get Surveys

You can use .getSurveys(completionHandler:) to get available surveys for the user. On success, the callback function returns a list of Surveys.

BitLabs.shared.getSurveys { result in
    switch result {
    case .failure(let error):
        print("[Example] Get Surveys \(error)")

    case .success(let surveys):
        print("[Example] \(surveys.map { "Survey \($0.id) in Category \($0.details.category.name)" })")
    }
}

The Survey object has the following properties:

networkIdIntThe id of the Network this survey belongs to.
idIntThe id of the Survey.
cpiStringCPI of this survey in USD without any formatting applied.
valueStringCPI formatted according to your app settings. Can be shown to the user directly.
loiDoubleAssumed length of the survey in minutes.
remainingIntAmount of users that can still open the survey.
detailsDetails(Category(name: String, IconUrl: String))The details of the category this Survey is classified in.
ratingIntDifficulty ranking of this survey. 1-5 (1 = hard, 5 = easy). Minimum value is 1, maximum value is 5.
linkStringThis link can be used as is to open the survey. All relevant details are inserted on the server.
missingQuestionsInt?The amount of questions that have to be answered before the survey is guaranteed to be openable by the user.
open()FunctionA function which opens the Offerwall.

Native Survey Widgets

You can use .getSurveyWidgets(surveys:parent:type:) to get a UICollectionView of Survey widgets.

let collection = BitLabs.shared.getSurveyWidgets(surveys: surveys, parent: self, type: .compact)

// surveysContainer is a container you add in your UI to contain the collections.
collection.frame = surveysContainer.bounds

surveysContainer.addSubview(collection)

The WidgetType can be one of three options:

Reward Completion Handler - Client Side Callbacks

You can use .setRewardCompletionHandler() to set a callback which receives the reward of the user and executes the behaviour you specify.

BitLabs.shared.setRewardCompletionHandler { reward in
    print("[Example] You earned: \(reward)")
}

This callback is invoked when the user leaves the Offer Wall, and the payout is the total reward the user got since the Offer Wall is opened until it is closed.

🚧

We highly recommend using server-to-server callbacks instead! Please do not use this in apps where the user can withdraw real currency, as it might be exploitable. However, if your app stores user data locally and does not sync with a server, this would be an option to still use BitLabs to reward your users.

Parameters

You can use .setTags() to pass additional parameters to the SDK you would like to receive in your callback.

BitLabs.shared.setTags(["display_mode": "offers", "theme": "DARK"])

🚧

Setting a new Dictionary of Tags will replace the old ones.

Add Parameters

Use .addTag() if you want to append new parameters to an already existent dictionary of parameters which you already set earlier.

BitLabs.shared.addTag(key: "display_mode", value: "offers")
BitLabs.shared.addTag(key: "theme", value: "DARK")

πŸ“˜

Helpful

You can find a list of existing parameters here.

Request Tracking Authorisation - For the Advertising Id

Since Offers work best with a device's Ad Id, we will need to fetch that Id and send it to the offer wall. In iOS, this can only be done after the user gives authorisation. So, we created a method which asks the user for authorisation. You can have the discretion of when it's best to ask the user in your app and call this one method whenever you want.

BitLabs.shared.requestTrackingAuthorization()

❗️

IMPORTANT

In order to be able to show the Tracking Authorization request, you have to provide a custom text, known as a usage-description string, which displays in the system-permission alert request. Basically, just add this value to your Info.plist as shown in this official page.

Leaderboard

The Leaderboard widget shows your top 100 earning users and their corresponding earnings in your app's currency. And will open the Offerwall if clicked.

Reward

The rewards shown in the widget are custom to your app and will be paid by us to you and your users. By default these rewards are disabled and not shown so this widget only serves the purpose to display the best earning users. To enable the rewards and incentivise your users to do more surveys and offers in your app please contact us on: [email protected]

The earnings will reset at the end of each month and the top 100 users will get their corresponding reward. If a user is listed in the leaderboard it will see it's rank by the blue (You) besides the username.

All earnings and rewards in the leaderboard will be formatted as your app's settings set on our publisher dashboard.

Username

If you implement the leaderboard without updating your offerwall and widget integration all users will just be called anonymous. To pass us the correct usernames to your provided user id you will have to add a tag with key username before launching the offerwall.

Implementation

You can use the getLeaderboardView(completionHandler:) to get a LeaderboardView which can be added as a Subview to any UIView you set as the parent.

BitLabs.shared.getLeaderboardView { leaderboard in
	guard let leaderboard = leaderboard else { return }

	leaderboard.frame = self.leaderboardContainer.bounds

	self.leaderboardContainer.addSubview(leaderboard)
}

Whitelist Domains

Since BitLabs works with a plethora of survey providers, we can't always make sure that the domains are secured with HTTPS schemes. So you need to whitelist some providers if needed.

For Specific Domains:

  1. Navigate to [ProjectRootDirectory]/ios/[ProjectDirectory]/info.plist
  2. Paste the following inside the main :
<key>NSAppTransportSecurity</key>  
	<dict>  
		<key>NSExceptionDomains</key>  
		<dict>  
			<key>samplicio.us</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
			<key>cint.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
			<key>qualtrics.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
			<key>spectrumsurveys.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
			<key>decipherinc.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
			<key>ssisurveys.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
			<key>lucidhq.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>paradigmsample.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>focusvision.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>vi.ga</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>opinionetwork.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>surveyrouter.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>opinionbar.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>prsrvy.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>ptrack1.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>globaltestmarket.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>  
        	<key>eocucom.com</key>  
			<dict>  
				<key>NSIncludesSubdomains</key>  
				<true/>  
				<key>NSExceptionAllowsInsecureHTTPLoads</key>  
				<true/>  
			</dict>		
		<key>prodegemr.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>swagbucks.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>sgizmo.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>surveygizmo.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>reviewrobin.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>questmindshare.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>peanutlabs.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>marketknowledgesurveys.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>dubinterviewer.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>confirmit.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>survia.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
    	<key>insights.supply</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
		<key>roirocket.com</key>
		<dict>
			<key>NSIncludesSubdomains</key>
			<true/>
			<key>NSExceptionAllowsInsecureHTTPLoads</key>
			<true/>
		</dict>
	</dict>
</dict

You can add or remove any domain to the above list.

If you want to allow any HTTP request instead, inside the info.plist put the following:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
      <true/>
</dict>

Your next Step

You have now implemented BitLabs with your project. If you haven't done it already, it is time to configure server-to-server callbacks and the look and feel of your app.