Flutter
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
minSdk24 - 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
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):
| Property | Type |
|---|---|
transactionIdentifier | String? |
placementIdentifier | String? |
placementTag | String? |
currencyName | String? |
rewardAmount | double? |
payoutEventType | PayoutTypes? — 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.
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(),
);
}
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
| Property | Type | Description |
|---|---|---|
surveyIdentifier | String | The Quick Question identifier. |
appName | String | Your app's name. |
apiToken | String | The app's API token. |
sdkVersion | String | The SDK version. |
platform | String | The platform. |
placementTag | String | The placement the Quick Question was shown on. |
userIdentifier | String | The user identifier. |
userLocale | String | The user's locale. |
seenAt | String | When the Quick Question was shown. |
complete | Complete? | completeIdentifier and completedAt. |
questions | List<Question> | Each Question has questionIdentifier, questionText, questionType and userAnswer (UserAnswer? with value and identifiers). |
targetAudience | List<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
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:
| Property | Type | Description |
|---|---|---|
name | String? | The name of the placement. |
contentType | String? | The type of content associated with the placement. |
currencyName | String? | The name of the currency rewarded by this placement. |
isSale | bool? | Indicates if there is an active sale. |
saleType | String? | The category or type of the active sale. |
saleEndDate | String? | When the sale expires (UTC date string). |
saleMultiplier | double? | The reward multiplier during a sale. |
saleDisplayName | String? | The display name for the sale. |
saleTag | String? | A tag associated with the sale. |
bonusBarProgress | TRBonusBarProgress? | The user's progress toward a bonus. |
TRBonusBarProgress class
| Property | Type | Description |
|---|---|---|
isActive | bool? | Indicates if the bonus bar is currently active. |
currentCompletes | int? | The number of survey completions achieved toward the bonus. |
bonusWindowEndAt | String? | When the bonus window expires (UTC date string). |
bonusTiers | List<TRBonusTier>? | A list of tiers available in the progress bar. |
error | TRError? | Error information if the progress could not be retrieved. |
TRBonusTier class
| Property | Type | Description |
|---|---|---|
tierNumber | int? | The sequence number of the tier. |
completesNeeded | int? | Number of completions required to reach this tier. |
rewardAmount | double? | The reward granted upon completing this tier. |
status | String? | The current status of the tier. |
Need help?
Email developers@tapresearch.com.
Stay updated: see tapresearch_flutter_plugin on pub.dev for new releases.