Skip to main content
Version: 3.x

Flutter

What you'll do
  1. Install the SDK
  2. Set up callbacks
  3. Initialize the SDK
  4. Display a placement

Later sections cover rewards, user attributes, the user identifier, Quick Questions, boosts, and placement details.

Installation​

The TapResearch Flutter plugin with an example app is available on GitHub: https://github.com/TapResearch/tapresearch_flutter_plugin/

Requirements​

  • Flutter 3.41.7 or later (Dart 3.11.5 or later)
  • Android minSdk 24
  • iOS 13.0 (iOS 15.0 from 3.8.1)

Add the plugin​

Replace <version> below with your SDK version from pub.dev.

Add the tapresearch_flutter_plugin to your pubspec.yaml file:

dependencies:
tapresearch_flutter_plugin: <version>

Or run the following command:

flutter pub add tapresearch_flutter_plugin:<version>

Integration​

Test mode

If your app is in test mode, you must use a test user. Configure test users in "Test Devices" on the dashboard.

Callbacks​

The SDK uses callbacks to notify your app of certain events. You should implement these interfaces and provide them to the SDK.

SDK ready callback​

This function will be called when the SDK is ready to show content.

class MySdkReadyCallback implements TRSdkReadyCallback {

void onTapResearchSdkReady() {
print("TapResearch SDK is ready");
}
}

Rewards callback​

The SDK will notify you when a user has earned rewards.

class MyRewardCallback implements TRRewardCallback {

void onTapResearchDidReceiveRewards(List<TRReward> rewards) {
for (var reward in rewards) {
print("Received reward: ${reward.rewardAmount} ${reward.currencyName}");
}
}
}

TRReward contains the following properties (see TRReward for a description of each field):

PropertyType
transactionIdentifierString?
placementIdentifierString?
placementTagString?
currencyNameString?
rewardAmountdouble?
payoutEventTypePayoutTypes? — profileReward (0), partialPayout (1), fullPayout (3, survey complete), quickQuestionsPayout (9)

Error callback​

Handle any errors that may occur. Errors are passed as a TRError with a code and a description.

class MyErrorCallback implements TRErrorCallback {

void onTapResearchDidError(TRError error) {
print("TapResearch Error: ${error.description} (Code: ${error.code})");
}
}

final onError = MyErrorCallback();

Content callbacks​

Notify your app when content is shown or dismissed. Pass a content callback to each showContentForPlacement or showSurveyForPlacement call.

class MyContentCallback implements TRContentCallback {

void onTapResearchContentShown(String placementTag) {
print("Content shown for $placementTag");
}


void onTapResearchContentDismissed(String placementTag) {
print("Content dismissed for $placementTag");
}
}

Initialization​

Initialize the TapResearch SDK as early as possible. It is required to use different API tokens for iOS and Android.

Tip

The user identifier passed through initialization must be unique per user! Only initialize once you are able to provide a unique identifier. Re-using the same user identifier is not supported and will prevent your users from accessing our service.

import 'dart:io';

import 'package:tapresearch_flutter_plugin/tapresearch_flutter_plugin.dart';

final _plugin = TapresearchFlutterPlugin();

void initTapResearch() {
final String apiToken = Platform.isAndroid ? "YOUR_ANDROID_API_TOKEN" : "YOUR_IOS_API_TOKEN";
final String userIdentifier = "YOUR_UNIQUE_USER_ID";

_plugin.initialize(
apiToken: apiToken,
userIdentifier: userIdentifier,
sdkReadyCallback: MySdkReadyCallback(),
errorCallback: onError,
rewardCallback: MyRewardCallback(),
);
}
Info

If user attributes are known at SDK initialization, it is preferable to pass them through userAttributes compared to using sendUserAttributes. This will result in quicker load times for targeted content.

_plugin.initialize(
apiToken: apiToken,
userIdentifier: userIdentifier,
sdkReadyCallback: MySdkReadyCallback(),
errorCallback: onError,
rewardCallback: MyRewardCallback(),
userAttributes: {
"age": 25,
"is_vip": 1,
},
clearPreviousAttributes: false,
);

Checking if the SDK is ready​

You can check if the SDK is ready using the isReady() method:

void checkSdkReady() async {
bool isReady = await _plugin.isReady();
print("SDK Ready: $isReady");
}

Displaying a placement​

You can check whether a placement is available by using canShowContentForPlacement(). It is recommended that you wrap showContentForPlacement calls with this check.

void showPlacement(String placementTag) async {
bool canShow = await _plugin.canShowContentForPlacement(placementTag, onError);

if (canShow) {
_plugin.showContentForPlacement(
tag: placementTag,
contentCallback: MyContentCallback(),
errorCallback: onError,
);
}
}

Passing custom parameters​

Custom parameters allow you to receive additional information about the user when they complete a survey.

void showPlacementWithCustomParameters(String placementTag) {
Map<String, dynamic> customParameters = {
"custom_param_1": "value1",
"is_vip": true,
};

_plugin.showContentForPlacement(
tag: placementTag,
customParameters: customParameters,
contentCallback: MyContentCallback(),
errorCallback: onError,
);
}

Sending user attributes​

User attributes are used to target content to specific users.

Attribute names must be strings and must not begin with tapresearch_, which is reserved for TapResearch. Use string or numeric values for targeting. For booleans, send "true"/"false" or 0/1 instead of native booleans.

Set clearPreviousAttributes to false to merge new values with existing attributes, or true to replace the attributes you previously sent.

void sendUserAttributes() {
Map<String, dynamic> userAttributes = {
"age": 25,
"gender": "female",
"is_vip": 1,
};

_plugin.sendUserAttributes(
userAttributes: userAttributes,
clearPreviousAttributes: false,
errorCallback: onError,
);
}

Updating user identifier​

You can set the user identifier at any time.

void updateUserIdentifier(String newUserId) {
_plugin.setUserIdentifier(newUserId);
}

Quick Questions​

New to Quick Questions? See Quick Questions for what they are, and Handling Quick Question Responses for other ways to receive the answers.

To receive Quick Question responses in your app, implement TRQQDataCallback and pass it to initialize as qqDataCallback. It is called whenever a user completes a Quick Question.

class MyQQDataCallback implements TRQQDataCallback {

void onQuickQuestionDataReceived(QQPayload data) {
print("Quick Question ${data.surveyIdentifier} answered on ${data.placementTag}");
for (final question in data.questions) {
print("${question.questionText}: ${question.userAnswer?.value}");
}
}
}

_plugin.initialize(
apiToken: apiToken,
userIdentifier: userIdentifier,
sdkReadyCallback: MySdkReadyCallback(),
errorCallback: onError,
qqDataCallback: MyQQDataCallback(),
);

QQPayload class​

PropertyTypeDescription
surveyIdentifierStringThe Quick Question identifier.
appNameStringYour app's name.
apiTokenStringThe app's API token.
sdkVersionStringThe SDK version.
platformStringThe platform.
placementTagStringThe placement the Quick Question was shown on.
userIdentifierStringThe user identifier.
userLocaleStringThe user's locale.
seenAtStringWhen the Quick Question was shown.
completeComplete?completeIdentifier and completedAt.
questionsList<Question>Each Question has questionIdentifier, questionText, questionType and userAnswer (UserAnswer? with value and identifiers).
targetAudienceList<Map<String, String>>?The targeting filters, each with filter_attribute_name, filter_operator, filter_value and user_value keys.

Grant boost​

Boosts are temporary reward multipliers that can be granted to users.

class MyGrantBoostListener implements TRGrantBoostResponseListener {

void onGrantBoostResponse(TRGrantBoostResponse response) {
if (response.success == true) {
print("Boost granted successfully: ${response.boostTag}");
} else {
print("Failed to grant boost: ${response.error?.description}");
}
}
}

void applyBoost(String boostTag) {
_plugin.grantBoost(
boostTag,
listener: MyGrantBoostListener(),
);
}

Getting placement details​

Don't cache placement details

Placement details can change as our SDK refreshes placements in the background, so it is not recommended to store or cache these values. Instead, refetch the details each time you need to use them, e.g. to display something in your UI.

Get placement details by calling getPlacementDetails(placementTag, errorListener: ...).

void getPlacementInfo(String placementTag) async {
TRPlacementDetails? details = await _plugin.getPlacementDetails(
placementTag,
errorListener: onError,
);

if (details != null) {
print("Placement Name: ${details.name}");
print("Is Sale Active: ${details.isSale}");
}
}

TRPlacementDetails class​

TRPlacementDetails contains the following properties:

PropertyTypeDescription
nameString?The name of the placement.
contentTypeString?The type of content associated with the placement.
currencyNameString?The name of the currency rewarded by this placement.
isSalebool?Indicates if there is an active sale.
saleTypeString?The category or type of the active sale.
saleEndDateString?When the sale expires (UTC date string).
saleMultiplierdouble?The reward multiplier during a sale.
saleDisplayNameString?The display name for the sale.
saleTagString?A tag associated with the sale.
bonusBarProgressTRBonusBarProgress?The user's progress toward a bonus.

TRBonusBarProgress class​

PropertyTypeDescription
isActivebool?Indicates if the bonus bar is currently active.
currentCompletesint?The number of survey completions achieved toward the bonus.
bonusWindowEndAtString?When the bonus window expires (UTC date string).
bonusTiersList<TRBonusTier>?A list of tiers available in the progress bar.
errorTRError?Error information if the progress could not be retrieved.

TRBonusTier class​

PropertyTypeDescription
tierNumberint?The sequence number of the tier.
completesNeededint?Number of completions required to reach this tier.
rewardAmountdouble?The reward granted upon completing this tier.
statusString?The current status of the tier.

Need help?​

Email developers@tapresearch.com.

Stay updated: see tapresearch_flutter_plugin on pub.dev for new releases.