ScateSDK Flutter Plugin

Installation

Install via CLI;

flutter pub add scatesdk_flutter

Or

Add the following into your pubspec.yaml file;

dependencies:
  scatesdk_flutter: ^7.0.22

Android Integration

To ensure that the ScateSDK works properly on Android, you need to add the Maven repository to your build.gradle file.

In your project's android/build.gradle file, add the following Maven repository:

repositories {
        // Other repositories
        maven {
            url "https://europe-west1-maven.pkg.dev/mavenrepo-433814/scatecoresdk-android"
        }
    }

⚠️ Attention ⚠️

In your android/app/build.gradle file, under buildTypes, please add the following lines:

buildTypes {
    release {
        minifyEnabled false
        shrinkResources false
    }
}

Note: If you enable minifyEnabled (code shrinking and obfuscation) in your build.gradle, you must keep ScateSDK classes to avoid issues with JSON serialization (such as @SerializedName fields turning into random letters).

To do this, add the following to your proguard-rules.pro file:

-keep class com.scate.scatesdk_flutter.** { *; }
-keepclassmembers class com.scate.scatesdk_flutter.** { *; }

iOS Integration

Purchases

ScateSDK notices purchases on its own; the app does not report them. Every time the app becomes active it sends StoreKit's transaction history to Scate, which keeps the purchases it has not seen before (iOS 15 and later). When the app uses Firebase Analytics, new purchases are also logged to Firebase as in_app_purchase, once each. No code is needed; do not also log purchases to Firebase yourself, or each one is counted twice.

Add SKIncludeConsumableInAppPurchaseHistory = YES to ios/Runner/Info.plist. Every app needs it: without it StoreKit drops a consumable from the history once it is finished (iOS 18 and later) and ScateSDK never sees that purchase. From 7.0.22, Init stops simulator, Xcode and TestFlight builds at launch while it is missing, so such a build cannot go to review; App Store builds keep running.

<key>SKIncludeConsumableInAppPurchaseHistory</key>
<true/>

Usage

Initialize the SDK

Register the remote config listener before initializing. It fires once per initialization and is not replayed, so a listener registered afterwards never sees it.

import 'dart:async';

import 'package:scatesdk_flutter/scatesdk_flutter.dart';


class _MyAppState extends State<MyApp> {
  
  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {

    final configsReady = Completer<bool>();
    ScateSDK.AddListener(ScateEvents.REMOTE_CONFIG_READY, (fetched) {
      if (!configsReady.isCompleted) configsReady.complete(fetched);
    });

    ScateSDK.Init("<your app id>");
    ScateSDK.InitAdjust("<your adjust token>");

    ScateSDK.GetAdjustId((adid) {
      // ADID is non-empty here.
    });

    await configsReady.future;

    // Nothing below this line runs before the configs are in:
    // read remote configs, then show the first screen.

  }

}

Do not read remote configs or show the first screen before the listener fires. Init returns immediately and never blocks on the network, so without this gate the app can render before any config has arrived. The listener always fires, true on a fresh fetch and false once retries are exhausted. A failing network is retried several times first, so if a slow network must not hold the splash, cap the wait at around five seconds and continue with cached or default values; a late answer still reaches the listener either way.

By default, on iOS, InitAdjust configures Adjust with a 120 second ATT consent wait interval and requests App Tracking Transparency authorization at init time. Add NSUserTrackingUsageDescription to the iOS app Info.plist for the prompt to appear. Pass noATT: true to skip ScateSDK's ATT request path:

ScateSDK.InitAdjust("<your adjust token>", noATT: true);

When an ADID is resolved, ScateSDK stores it as the SDK ADID and sends scate_adjust_id once after ScateSDK is initialized. If your app already initializes Adjust, avoid calling InitAdjust a second time; keep your app-owned Adjust setup and call ScateSDK.GetAdjustId(...) after Adjust is ready, or continue to use ScateSDK.SetAdid(adid).

By default, on iOS, when Firebase Analytics is linked and configured in the host app, ScateSDK sets Firebase user_id to the Scate user ID during initialization. If your app already manages Firebase user_id, disable this before initialization:

ScateSDK.Init(
  "<your app id>",
  firebaseUserIdSyncEnabled: false,
);

Send Events

To send events, you can use the following code:

    
ScateSDK.Event("button_clicked");

Send Events with Parameters


ScateSDK.Event("button_clicked", parameters: {
  "screen": "paywall",
  "position": 1,
  "isPrimary": true,
});

Send Events with Additional Data


ScateSDK.EventWithValue("button_clicked", "subscribe_btn");

Send Events with Additional Data and Parameters


ScateSDK.EventWithValueAndParameters("button_clicked", "subscribe_btn", parameters: {
  "screen": "paywall",
  "position": 1,
  "isPrimary": true,
});

Get Remote Config for Key


ScateSDK.GetRemoteConfig('key', 'defaultValue');

// Typed reads fall back to the default when the value is not of that type.
final enabled = await ScateSDK.GetRemoteConfigBool('new_camera', false);
final limit = await ScateSDK.GetRemoteConfigInt('scan_limit', 10);
final ratio = await ScateSDK.GetRemoteConfigDouble('crop_ratio', 1.5);

Add Listener

ScateSDK.AddListener(ScateEvents.REMOTE_CONFIG_READY, (event) => {});

Remove Listener

ScateSDK.RemoveListener(ScateEvents.REMOTE_CONFIG_READY);

Clean Listeners

ScateSDK.CleanListeners(ScateEvents.REMOTE_CONFIG_READY);

Onboarding Event Functions

ScateSDK.OnboardingStart();
ScateSDK.OnboardingStep("location_screen");
ScateSDK.OnboardingStep("notification_screen");
ScateSDK.OnboardingStep("personalization_screen");
ScateSDK.OnboardingStep("journey_screen");
ScateSDK.OnboardingStep("intro_paywall_screen");
ScateSDK.OnboardingStep("fullscreen_ad");
ScateSDK.OnboardingFinish();

Login Event Functions

ScateSDK.LoginSuccess("apple");
ScateSDK.LoginSuccess("email");
ScateSDK.LoginSuccess("fb");
ScateSDK.LoginSuccess("google");

Ad Event Functions

ScateSDK.InterstitialAdShown();
ScateSDK.InterstitialAdClosed();
ScateSDK.RewardedAdShown();
ScateSDK.RewardedAdClosed();
ScateSDK.RewardedAdClaimed();
ScateSDK.BannerAdShown();

Permission Event Functions

ScateSDK.NotificationPermissionGranted();
ScateSDK.NotificationPermissionDenied();
ScateSDK.LocationPermissionGranted();
ScateSDK.LocationPermissionDenied();
ScateSDK.ATTPromptShown();
ScateSDK.ATTPermissionGranted();
ScateSDK.ATTPermissionDenied();

Paywall Event Functions

ScateSDK.PaywallShown("paywall_name");
ScateSDK.PaywallClosed("paywall_name");
ScateSDK.PaywallAttempted("paywall_name");
ScateSDK.PaywallPurchased("paywall_name");
ScateSDK.PaywallCancelled("paywall_name");

Tab And Feature Event Functions

ScateSDK.TabClicked("x");
ScateSDK.FeatureClicked("x");

Daily Streak Event Functions

ScateSDK.DailyStreakShown();
ScateSDK.DailyStreakClaimed();
ScateSDK.DailyStreakClosed();

Adjust And Revenuecat Event Functions

ScateSDK.RevenuecatInitiated();
ScateSDK.AdjustInitiated();
ScateSDK.AdjustSetToRevenuecat();

Splash Event Function

ScateSDK.SplashCompleted();

Firebase Event Function

ScateSDK.FirebaseRemoteInitiated();

Home Screen Event Function

ScateSDK.HomeScreenOpen();

Onboarding Paywall Event Functions

ScateSDK.OnboardingPaywallShown();
ScateSDK.OnboardingPaywallClosed();

Event List Screen Function (IOS Only)

ScateSDK.ShowEventList();

Onboarding And Paywall Screen Functions and Events

Show Paywall Screen

ScateSDK.ShowPaywall("jsonString");

Close Paywall Screen

ScateSDK.ClosePaywall();

Show Onboarding Screen

ScateSDK.ShowOnboarding("jsonString");

Close Onboarding Screen

ScateSDK.CloseOnboarding();

Show Paid Product Loading Screen

ScateSDK.ShowPaidProductLoadingScreen();

Close Paid Product Loading Screen

ScateSDK.ClosePaidProductLoadingScreen();

Paywall And Onboarding Screen Events

  ScateSDK.AddListener(ScateEvents.ONBOARDING_SCREENS_FINISHED, (identifier) => {});
  ScateSDK.AddListener(ScateEvents.PAYWALL_SCREEN_FINISHED,(identifier) => {});
  ScateSDK.AddListener(ScateEvents.PAID_PRODUCT_CLICKED, (identifier) => {});
  ScateSDK.AddListener(ScateEvents.PAYWALL_SCREEN_CLOSED, (success) => {});
  ScateSDK.AddListener(ScateEvents.ONBOARDING_SCREEN_CLOSED, (success) => {});
  ScateSDK.AddListener(ScateEvents.RESTORE_PURCHASE_CLICKED, (success) => {});