Skip to content

iteratehq/iterate-android

Repository files navigation

Iterate for Android

build version Maven Central license


Iterate surveys put you directly in touch with your app users to learn how you can change for the better—from your product to your app experience.

Run surveys that are highly targeted, user-friendly, and on-brand. You’ll understand not just what your visitors are doing, but why.

Requirements

This SDK requires Android 5.0 Lollipop (API level 21) or higher.

Install

Ensure that you include the Maven Central repository on your root folder build.gradle file.

buildscript {
    repositories {
        ...
        mavenCentral()
    }
}

Add the latest iterate dependency to your app/build.gradle file.

dependencies {
    implementation "com.iteratehq:iterate:<latest_version>"
}

Usage

Within your app, surveys are shown in response to events. An event can be anything from viewing a screen, clicking a button, or any other user action. You use the Iterate SDK to send events to Iterate, then from your Iterate dashboard you create surveys that target those events.

Quick start

Create your Iterate account if you haven't already.

  1. Create a new survey and select "Install in your mobile app"
  2. Go to the "Preview & Publish" tab and copy your SDK API key
  3. Initialize the SDK in the onCreate() method of your Application subclass or an Activity.
import com.iteratehq.iterate.Iterate

class IterateApp : Application() {

    override fun onCreate() {
        // ...
        Iterate.init(this, API_KEY)
    }
}
  1. Implement events

Here's an example of an event being fired when the user views the activity feed screen

import com.iteratehq.iterate.Iterate

class ActivityFeedActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        Iterate.sendEvent("viewed-activity-feed", supportFragmentManager)
    }
}
  1. Create your survey on iteratehq.com and target it to that event
  2. Publish your survey and you're done 🎉

Previewing your survey

You'll likely want to preview your survey before publishing it so you can test that everything works correctly. When previewing a survey you'll be able to see a survey before it's published. When previewing a survey all targeting options for that survey are ignored (e.g. rate limiting, targeting user properties), the only thing you need to do is trigger the event that your survey is targeting and it will show up.

  1. In the "Preview & Publish" tab select 'Android' and copy the preview code.
  2. Implement Iterate.preview into your application, this can be done once in any component that's rendered before the event you're targeting
override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    Iterate.preview("your-survey-id")
}

Recommendations

When implementing Iterate for the first time, we encourage you to implement events for all of your core use cases which you may want to target surveys to in the future. e.g. sign up, purchased, viewed X screen, tapped notification, etc. This way you can easily launch new surveys targeting these events without needing to instrument a new event each time.

Custom fonts

Custom fonts can be used in the Iterate survey view by adding the font files to your assets folder, and passing their paths (relative to /assets) to the Iterate.init method, like this:

Iterate.init(this, API_KEY, null, "Merriweather-Regular.ttf", "WorkSans-VariableFont_wght.ttf")

The font specified in the buttonFontName parameter will be used in all survey interface buttons (question responses, previous / next buttons, etc). The font specified in surveyTextFontName will be used for all other survey text (question prompts, explanatory copy, etc).

True Type fonts and Open Type Fonts are supported.

Associating data with a user

Using the identify method, you can easily add 'user properties' to a user that can be used to target surveys to them and associate the information with all of their future responses. We recommend setting the external_id (needs to be a string) which represents your internal id for the user, this allows us to associate this user across multiple platforms and sessions'

fun onLoginSuccessful() {
    Iterate.identify(
        UserTraits(
            "external_id" to "12abc34",
            "email" to "example@email.com",
            "date_joined" to Date()
        )
    )
}

You can also associate 'response properties' with the user's responses to a specific survey (not associated with any future surveys they fill out), by passing an object to the sendEvent method.

fun onActivityFeedViewed() {
    Iterate.sendEvent(
        "viewed-activity-feed",
        supportFragmentManager,
        EventTraits(
            "selected_product_id" to 12345
        )
    )
}

For more information see our help article.

Event callbacks

If you need access to the user's responses on the client, you can use the onResponse method to pass a callback function that will return the question and response

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    Iterate.onResponse { response, question, survey ->
        // Your logic here
    }
}

If you need access to other events on the survey (dismiss, survey-complete, etc), you can use the onEvent method to pass a callback function that will fire with each of the events listed below

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    Iterate.onEvent { type, data ->
        // Your logic here
    }
}
Event Data Notes
"dismiss" data class InteractionEventDismissData(val progress: ProgressEventMessageData?, val source: InteractionEventSource, val survey: Survey)

data class ProgressEventMessageData(val completed: Int, val total: Int, val currentQuestion: Question?)
progress contains data about how far the user was in the survey when they dismissed. completed is number of questions they've completed (regardless of if they responded to the question or skipped it). total is the total number of questions in the survey. currentQuestion is the question they were on when they dismissed the survey.
"displayed" data class InteractionEventDisplayedData(val source: InteractionEventSource, val survey: Survey)
"response" data class InteractionEventResponseData(val response: Response, val question: Question, val survey: Survey)
"survey-complete" data class InteractionEventSurveyCompleteData(val survey: Survey) Called once when the user reaches the 'thank you' screen

Clearing data

To clear all data Iterate has stored (user api key, any user properties stored by calling the identify method, etc) call the reset method. This is commonly called when you log a user out of your app.

fun logout() {
    Iterate.reset()
    // Your other logout logic here
}

Survey eligibility and frequency

By default surveys are only shown once per person and user's can only see at most 1 survey every 72 hours (which is configurable). You can learn more about how eligibility and frequency works.

Using Encrypted Storage

By default we make use of EncryptedSharedPreferences to store the user's API key as well as a few other pieces of data (timestamp they last saw a survey, etc). There is a known rare bug in Android where certain devices will corrupt the master key, causing the following runtime exception to be thrown java.security.KeyStoreException: the master key android-keystore://_androidx_security_master_key_ exists but is unusable. More on the bug here and here. The solution is to use the unencrypted SharedPreferences instead of EncryptedSharedPreferences. We've decided to continue to use EncryptedSharedPreferences by default since the bug effects a very small number of devices and prefer to encrypt all data when possible, however if you wish to use the unencrypted SharedPreferences to avoid this crash you can do so by initializing Iterate with the useEncryptedSharedPreferences = false parameter as shown below.

Iterate.init(this, API_KEY, useEncryptedSharedPreferences = false)

Troubleshooting

If you have any issues you can head over to our help center to search for an answer or chat with our support team.