Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CLEVERTAP_ACCOUNT_ID=your_account_id_here
CLEVERTAP_ACCOUNT_TOKEN=your_token_here
CLEVERTAP_ACCOUNT_REGION=your_region_here # Optional
CLEVERTAP_HANDSHAKE_DOMAIN=your_handshake_domain_here # Optional
85 changes: 67 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://github.com/CleverTap/clevertap-ios-sdk/blob/master/docs/images/clevertap-logo.png" width = "50%"/>
<img src="https://github.com/CleverTap/clevertap-ios-sdk/blob/master/docs/images/clevertap-logo.png" width="50%" alt="CleverTap Logo"/>
</p>

# CleverTap Flutter SDK
Expand All @@ -8,48 +8,97 @@
<img src="https://img.shields.io/github/release/CleverTap/clevertap-flutter.svg" />
</a>

## 👋 Introduction
## Introduction
The CleverTap Flutter SDK for Mobile Customer Engagement and Analytics solutions.

For more information check out our [website](https://clevertap.com/ "CleverTap") and [documentation](https://developer.clevertap.com/docs/ "CleverTap Technical Documentation").
For more information, check out our [website](https://clevertap.com/) and [documentation](https://developer.clevertap.com/docs/).

To get started, sign up [here](https://clevertap.com/live-product-demo/).

## 🚀 Installation and Quick Start
## Installation and Quick Start

- To add the **CleverTap Flutter SDK** to your project, edit your project's `pubspec.yaml` file:

```yaml
dependencies:
clevertap_plugin: 3.2.0
clevertap_plugin: 3.2.0
```

- Run `flutter packages get` to install the SDK
- Run `flutter packages get` to install the SDK.

- Now, in your Dart code, you can use:

```dart
import 'package:clevertap_plugin/clevertap_plugin.dart';
```

See our [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) for instructions on integrating CleverTap into your Flutter app.
### Initialize CleverTap

## 📑 Documentation & Example
You can initialize CleverTap using either:

- Checkout our [CleverTap Flutter Usage documentation](doc/Usage.md)
- Checkout our [Example Dart project](./example)
1. **Platform-specific configuration files (recommended):**
- Follow the instructions in [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md)

## 📲 CleverTap Push Templates SDK (Available only for Android OS)
[(Back to top)](#-table-of-contents)
2. **Using environment variables:**
- Copy `.env.example` to `.env` in your project root:
```bash
cp .env.example .env
```
- Update the `.env` file with your CleverTap credentials:
```
CLEVERTAP_ACCOUNT_ID=your_account_id_here
CLEVERTAP_ACCOUNT_TOKEN=your_token_here
CLEVERTAP_ACCOUNT_REGION=your_region_here # Optional
CLEVERTAP_HANDSHAKE_DOMAIN=your_domain_here # Optional
```

CleverTap Push Templates SDK helps you engage with your users using fancy push notification templates built specifically to work with [CleverTap](https://www.clevertap.com).
Find the integration steps for the CleverTap Push Templates SDK [here](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTPUSHTEMPLATES.md)
3. **Programmatically in your Flutter code:**
```dart
await CleverTapPlugin.initialize(
accountId: 'YOUR_ACCOUNT_ID',
token: 'YOUR_ACCOUNT_TOKEN',
region: 'YOUR_REGION', // Optional
targetDomain: 'YOUR_DOMAIN' // Optional
);
```

## 🆕 Changelog
See our [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) for complete instructions on integrating CleverTap into your Flutter app.

Refer to the [CleverTap Flutter SDK Change Log](./CHANGELOG.md).
## Security Measures

To ensure secure handling of CleverTap credentials and sensitive data, follow these best practices:

- **Environment Variable Management:**
- Always add `.env` to your `.gitignore` to prevent accidental commits of sensitive credentials.
- Never store production credentials in the source code or version control.
- Use separate credentials for development, staging, and production environments.

- **Secure Credential Handling:**
- Utilize secret management tools such as AWS Secrets Manager, Google Secret Manager, or environment variable injection via CI/CD pipelines.
- Ensure access to credentials is restricted to authorized team members only.
- Regularly rotate API keys and tokens to minimize security risks.

- **CI/CD Pipeline Security:**
- Store secrets in a secure vault instead of hardcoding them in configuration files.
- Use least privilege access policies for CI/CD tools interacting with CleverTap.
- Monitor logs for unauthorized access attempts.

By implementing these security practices, you can safeguard your application and user data.

## ❓Questions
## Documentation & Example

- Check out our [CleverTap Flutter Usage documentation](doc/Usage.md).
- Check out our [Example Dart project](./example).

## CleverTap Push Templates SDK (Available only for Android OS)

CleverTap Push Templates SDK helps you engage with your users using dynamic push notification templates built specifically for [CleverTap](https://www.clevertap.com).
Find the integration steps for the CleverTap Push Templates SDK [here](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTPUSHTEMPLATES.md).

## Changelog

Refer to the [CleverTap Flutter SDK Change Log](./CHANGELOG.md).

If you have questions or concerns, you can reach out to the CleverTap support team from the CleverTap Dashboard.
## Questions

If you have questions or concerns, you can reach out to the CleverTap support team from the CleverTap Dashboard.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class CleverTapApplication extends Application implements CTPushNotificat

@Override
public void onCreate() {
ActivityLifecycleCallback.register(this); // Register ActivityLifecycleCallback automatically
super.onCreate();
CleverTapAPI cleverTapAPI = CleverTapAPI.getDefaultInstance(this);
if (cleverTapAPI != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class DartToNativePlatformCommunicator(
result: MethodChannel.Result
) {
when (call.method) {
"initialize" -> {
initializeCleverTap(call = call, result = result)
}
"startEmission" -> {
startEmission(call = call, result = result)
}
Expand Down Expand Up @@ -2088,6 +2091,29 @@ class DartToNativePlatformCommunicator(

}

private fun initializeCleverTap(call: MethodCall, result: MethodChannel.Result) {
val accountId = call.argument<String>("accountId")
val token = call.argument<String>("token")
val region = call.argument<String>("region")

if (accountId == null || token == null) {
result.error(TAG, "accountId and token are required for initialization", null)
return
}

try {
val configMap = CleverTapAPI.getDefaultInstance(context)?.config
configMap?.let {
it.accountId = accountId
it.accountToken = token
region?.let { reg -> it.accountRegion = reg }
}
result.success(null)
} catch (e: Exception) {
result.error(TAG, "Failed to initialize CleverTap: ${e.message}", null)
}
}

private fun interface TemplateContextAction {
fun execute(context: CustomTemplateContext): Any?
}
27 changes: 12 additions & 15 deletions doc/Integrate-Android.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,6 @@
apply plugin: 'com.google.gms.google-services' //skip if not using FCM
```

- In your app's Android Application class add the following code.

```java
public class MyApplication extends Application {
@java.lang.Override
public void onCreate() {
ActivityLifecycleCallback.register(this); //<--- Add this before super.onCreate()
super.onCreate();
}
}

```

#### Note

- To use Header & Footer InApp Notification Templates of CleverTap, change the class from which MainActivity is inherited from `FlutterActivity` to `FlutterFragmentActivity`
Expand Down Expand Up @@ -90,15 +77,25 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
```

- Add your CleverTap Account ID and Token to your `AndroidManifest.xml`, within the <application></application> tags.

- Add your CleverTap Account ID and Token either:
1. In your `AndroidManifest.xml`, within the <application></application> tags:
```xml
<meta-data
android:name="CLEVERTAP_ACCOUNT_ID"
android:value="Your CleverTap Account ID"/>
<meta-data
android:name="CLEVERTAP_TOKEN"
android:value="Your CleverTap Account Token"/>
```
2. Or through environment variables in a .env file and initialize in your code:
```dart
await CleverTapPlugin.initialize(
accountId: 'YOUR_ACCOUNT_ID',
token: 'YOUR_ACCOUNT_TOKEN',
region: 'YOUR_REGION', // Optional
targetDomain: 'YOUR_DOMAIN' // Optional
);
```
<!-- IMPORTANT: To force use Google AD ID to uniquely identify users, use the following meta tag. GDPR mandates that if you are using this tag, there is prominent disclousure to your end customer in their application. Read more about GDPR here - https://clevertap.com/blog/in-preparation-of-gdpr-compliance/ -->
<meta-data
android:name="CLEVERTAP_USE_GOOGLE_AD_ID"
Expand Down
13 changes: 12 additions & 1 deletion doc/Integrate-iOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@

After installation, you will need to integrate CleverTap SDK into your app.

* Follow the integration instructions [starting with Step 2 here](https://developer.clevertap.com/docs/ios-quickstart-guide#section-step-2-add-clever-tap-credentials).
* Configure CleverTap credentials using one of these methods:
1. Follow the integration instructions [starting with Step 2 here](https://developer.clevertap.com/docs/ios-quickstart-guide#section-step-2-add-clever-tap-credentials).
2. Or initialize programmatically in your Flutter code:
```dart
await CleverTapPlugin.initialize(
accountId: 'YOUR_ACCOUNT_ID',
token: 'YOUR_ACCOUNT_TOKEN',
region: 'YOUR_REGION', // Optional
targetDomain: 'YOUR_DOMAIN' // Optional
);
```

* Initialize CleverTap SDK by adding the following code snippet:
+ Import the CleverTap header in your AppDelegate file

Expand Down
14 changes: 0 additions & 14 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="CLEVERTAP_ACCOUNT_ID"
android:value="CLEVERTAP_ACCOUNT_ID"/>
<meta-data
android:name="CLEVERTAP_TOKEN"
android:value="CLEVERTAP_TOKEN"/>
<meta-data
android:name="CLEVERTAP_REGION"
android:value="CLEVERTAP_REGION"/>

<meta-data
android:name="CLEVERTAP_HANDSHAKE_DOMAIN"
android:value="YOUR HANDSHAKE DOMAIN"/>

<!-- IMPORTANT: To force use Google AD ID to uniquely identify users, use the following meta tag. GDPR mandates that if you are using this tag, there is prominent disclousure to your end customer in their application. Read more about GDPR here - https://clevertap.com/blog/in-preparation-of-gdpr-compliance/ -->
<meta-data
android:name="CLEVERTAP_USE_GOOGLE_AD_ID"
Expand Down
6 changes: 0 additions & 6 deletions example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>CleverTapAccountID</key>
<string>CLEVERTAP_ACCOUNT_ID</string>
<key>CleverTapToken</key>
<string>CLEVERTAP_ACCOUNT_TOKEN</string>
<key>CleverTapRegion</key>
<string>CLEVERTAP_ACCOUNT_REGION</string>
<key>CleverTapUseIFA</key>
<false/>
<key>LSRequiresIPhoneOS</key>
Expand Down
19 changes: 18 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ void main() async {
CleverTapPlugin.onKilledStateNotificationClicked(
onKilledStateNotificationClickedHandler);

// Initialize CleverTap with your credentials (Optional)
await CleverTapPlugin.initialize(
accountId: 'YOUR_ACCOUNT_ID',
token: 'YOUR_ACCOUNT_TOKEN',
region: 'YOUR_REGION', // Optional
targetDomain: 'YOUR_DOMAIN' // Optional
);

print("CleverTapPlugin main pre runapp");

Future.delayed(Duration(seconds: TEST_RUN_APP_DELAY), () {
Expand Down Expand Up @@ -122,7 +130,16 @@ class _MyAppState extends State<MyApp> {
});
CleverTapPlugin.setDebugLevel(3);
if (kIsWeb) {
CleverTapPlugin.init("CLEVERTAP_ACCOUNT_ID", "CLEVERTAP_REGION", "CLEVERTAP_TARGET_DOMAIN");
// @deprecated Use initialize() method instead. This method will be removed in a future release.
// @deprecated: Use CleverTapPlugin.initialize() instead.
// Example of new initialization:
// await CleverTapPlugin.initialize(
// accountId: "CLEVERTAP_ACCOUNT_ID",
// token: "YOUR_ACCOUNT_TOKEN",
// region: "CLEVERTAP_REGION",
// targetDomain: "CLEVERTAP_TARGET_DOMAIN"
// );
CleverTapPlugin.init("CLEVERTAP_ACCOUNT_ID", "CLEVERTAP_REGION", "CLEVERTAP_TARGET_DOMAIN"); // deprecated
CleverTapPlugin.setDebugLevel(3);
CleverTapPlugin.addKVDataChangeListener((obj) {
var kv = obj["kv"];
Expand Down
5 changes: 0 additions & 5 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ flutter:
# the material Icons class.
uses-material-design: true

# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg

# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.

Expand Down
29 changes: 29 additions & 0 deletions ios/Classes/CleverTapPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ @interface CleverTapPlugin () <CleverTapSyncDelegate, CleverTapInAppNotification
@property (strong, nonatomic) FlutterMethodChannel *nativeToDartMethodChannel;
@property(nonatomic, strong) NSMutableDictionary *allVariables;


- (void)initializeWithConfig:(FlutterMethodCall *)call withResult:(FlutterResult)result {
NSDictionary *config = call.arguments;
NSString *accountId = config[@"accountId"];
NSString *token = config[@"token"];
NSString *region = config[@"region"];

if (!accountId || !token) {
result([FlutterError errorWithCode:@"CleverTapError"
message:@"accountId and token are required for initialization"
details:nil]);
return;
}

CleverTapInstanceConfig *instanceConfig = [[CleverTapInstanceConfig alloc] initWithAccountId:accountId
accountToken:token];
if (region) {
instanceConfig.regionCode = region;
}

NSString *targetDomain = config[@"targetDomain"];
if (targetDomain) {
instanceConfig.domain = targetDomain;
}

[CleverTap instanceConfigWithConfig:instanceConfig];
result(nil);
}

@end

static NSDateFormatter *dateFormatter;
Expand Down
24 changes: 23 additions & 1 deletion lib/clevertap_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,29 @@ class CleverTapPlugin {
return CleverTapAppLaunchNotification.fromMap(result);
}

/// Only for Web - Initialize clevertap sdk
/// Initialize the CleverTap SDK
static Future<void> initialize({
required String accountId,
required String token,
String? region,
String? targetDomain,
}) async {
final initProps = {
'accountId': accountId,
'token': token,
'region': region,
'targetDomain': targetDomain,
};

if (kIsWeb) {
await _dartToNativeMethodChannel.invokeMethod<void>('init', initProps);
} else {
await _dartToNativeMethodChannel.invokeMethod<void>('initialize', initProps);
}
}

/// Only for Web - Initialize clevertap sdk directly with parameters (legacy method)
@Deprecated('Use initialize() instead')
static Future<void> init(String accountId,
[String? region, String? targetDomain, String? token]) async {
if (!kIsWeb) {
Expand Down