adstart_flutter_sdk 0.1.4 copy "adstart_flutter_sdk: ^0.1.4" to clipboard
adstart_flutter_sdk: ^0.1.4 copied to clipboard

Flutter SDK for Adstart event collection.

Adstart Flutter SDK #

Flutter wrapper for Adstart event collection.

The SDK sends session, screen, sign-up, logout, customer identification, catalog, search, wishlist, cart, checkout, purchase, engagement, and custom events. It persists a deviceId across app launches and creates a new sessionId for every call to init().

Installation #

Add the package from pub.dev:

flutter pub add adstart_flutter_sdk

Or add it directly to pubspec.yaml:

dependencies:
  adstart_flutter_sdk: ^0.1.4

Then run flutter pub get.

Installation from Git #

To test an unreleased branch, use the Git repository:

dependencies:
  adstart_flutter_sdk:
    git:
      url: https://github.com/adstart-team/adstart-flutter-sdk.git
      ref: branch-or-commit

Usage #

Configure and initialize the Firebase project for the current business before calling AdstartSdk.init(). Follow the FlutterFire setup for Android and iOS, including the APNs configuration required by Firebase Cloud Messaging on iOS.

import 'package:firebase_core/firebase_core.dart';
import 'package:adstart_flutter_sdk/adstart_flutter_sdk.dart';

await Firebase.initializeApp();

final adstart = AdstartSdk(hashedId: 'your-hashed-id', debug: true);
final sessionId = await adstart.init(
  onPushEvent: (event) {
    switch (event.type) {
      case AdstartPushEventType.received:
        // The app owns foreground presentation, if any.
        debugPrint('Push received: ${event.notification?.title}');
      case AdstartPushEventType.opened:
        // Forward the destination to Navigator, go_router, or another router.
        final deepLink = event.deepLink;
        if (deepLink != null) {
          debugPrint('Open $deepLink');
        }
    }
  },
);

await adstart.addProductToWishlist(
  WishlistProductEventParams(
    currency: 'BRL',
    items: [
      AdstartItem(
        itemId: 'product-123',
        itemName: 'Product name',
        price: 249.90,
      ),
    ],
    source: 'product_detail',
  ),
);

await adstart.removeProductFromWishlist(
  WishlistProductEventParams(
    currency: 'BRL',
    items: [AdstartItem(itemId: 'product-123', price: 249.90)],
  ),
);

await adstart.viewWishlist(
  const WishlistViewEventParams(source: 'account_menu'),
);

await adstart.addProductToCart(
  EcommerceEventParams(
    currency: 'BRL',
    items: [AdstartItem(itemId: 'product-123', price: 249.90)],
  ),
);

await adstart.removeProductFromCart(
  EcommerceEventParams(
    currency: 'BRL',
    items: [AdstartItem(itemId: 'product-123', price: 249.90)],
  ),
);

final cart = EcommerceEventParams(
  currency: 'BRL',
  items: [
    AdstartItem(itemId: 'product-123', price: 249.90, quantity: 2),
  ],
);

await adstart.viewCart(cart);

final checkout = CheckoutEventParams(
  currency: 'BRL',
  items: cart.items,
  coupon: 'WELCOME10',
);

await adstart.addPaymentInfo(checkout);
await adstart.addShippingInfo(checkout);
await adstart.initiateCheckout(checkout);

await adstart.purchase(
  PurchaseEventParams(
    currency: checkout.currency,
    items: checkout.items,
    coupon: checkout.coupon,
    orderId: 'order-123',
    shippingValue: 19.90,
  ),
);

await adstart.productViewed(
  EcommerceEventParams(
    currency: 'BRL',
    items: [
      AdstartItem(
        itemId: 'product-123',
        itemName: 'Product name',
        price: 249.90,
        itemBrand: 'Brand name',
        itemCategory: 'Category name',
      ),
    ],
  ),
);

await adstart.categoryViewed(name: 'Category name');
await adstart.brandViewed(name: 'Brand name');
await adstart.searchedFor(searchTerm: 'black shoes');
await adstart.screenVisited(
  ScreenEventParams(
    name: 'product_list',
    attributes: <String, Object?>{
      'filters': <Map<String, Object?>>[
        <String, Object?>{
          'field': 'brand',
          'operator': 'equals',
          'value': 'Nike',
        },
        <String, Object?>{
          'field': 'price',
          'operator': 'between',
          'value': <num>[100, 500],
        },
      ],
      'source': 'home',
    },
  ),
);
await adstart.signUp();
await adstart.logout();

await adstart.trackTimeOnPage(TimeOnPageEventParams(seconds: 45));
await adstart.trackScrollDepth(ScrollDepthEventParams(depth: 50));

await adstart.customerIdentified(
  CustomerIdentificationEventParams(
    email: 'customer@example.com',
    customerExternalId: 'customer-123',
  ),
);

await adstart.trackCustomEvent(
  'product_compared',
  eventParams: <String, Object?>{
    'productIds': <String>['product-123', 'product-456'],
    'source': 'comparison_screen',
  },
);

adstart.dispose();

Call init() before sending events. All events sent after initialization reuse the active session's hashedId, deviceId, sessionId, and environment metadata.

Sign-up event #

Call signUp() after the application successfully completes a new account registration. It emits the standard Adstart sign_up event with empty eventParams and no eventKey.

The Adstart event ingestion contract must include the native sign_up event type before production can accept this event. Sign-up remains distinct from login and customer identification.

Logout event #

Call logout() after the application successfully completes a user logout. It emits the standard Adstart logout event with empty eventParams and no eventKey. It does not revoke push permissions, delete the FCM token, or end the active SDK session.

The Adstart event ingestion contract must include the native logout event type before production can accept this event.

Ecommerce and catalog events #

AdstartItem is the shared public item model for wishlist, cart, checkout, purchase, and product view events. Each item requires a finite, non-negative price, a positive quantity that defaults to 1, and at least one non-empty itemId or itemName. It also supports affiliation, item-level coupon and discount, position, brand, five category levels, list information, variant, and location.

EcommerceEventParams requires a non-empty item list and a three-letter currency code. Currency is trimmed and normalized to uppercase. The SDK derives the emitted value by summing price * quantity for all items with decimal accumulation; callers cannot provide a conflicting value.

Use WishlistProductEventParams when the optional source is useful. Use CheckoutEventParams for payment, shipping, and checkout events; its coupon is optional and is omitted from the payload when absent or blank.

Use PurchaseEventParams for purchase events. It requires a non-empty orderId and a finite, non-negative shippingValue, in addition to currency and items. Its optional coupon is omitted when absent or blank. The SDK keeps shippingValue separate and derives value exclusively from price * quantity across the items.

The public methods preserve Adstart event names:

Method eventType Required parameters
addProductToWishlist added_to_wishlist currency, items
removeProductFromWishlist removed_from_wishlist currency, items
addProductToCart added_to_cart currency, items
removeProductFromCart removed_from_cart currency, items
viewCart view_cart currency, items
addPaymentInfo added_payment_info currency, items
addShippingInfo added_shipping_info currency, items
initiateCheckout checkout_initiated_by currency, items
purchase purchase currency, items, orderId, shippingValue
productViewed product_viewed currency, items
screenVisited page_viewed name
categoryViewed category_viewed name
brandViewed brand_viewed name
searchedFor search searchTerm
signUp sign_up none
logout logout none

searchedFor emits the term as eventParams.search_term. The Adstart event ingestion contract must include the search event type before production can accept this event.

Screen visits #

Call screenVisited when the application confirms that a native screen has been displayed. ScreenEventParams requires a non-empty screen name and accepts optional dynamic attributes. Attributes are flattened into eventParams, may contain JSON-compatible nested lists and maps, and cannot use the reserved name key.

The SDK emits page_viewed but does not install a global observer for Navigator, go_router, or WebView navigation. The integrating application owns the moment when a screen visit is reported.

Customer identification #

Use customerIdentified after init() to associate identity data with the current device. At least one non-empty email, phone, or document is required. name, customerExternalId, and gender are optional. gender, when provided, is typed as CustomerGender.male or CustomerGender.female.

Only these canonical identity fields are sent in eventParams; session and device identifiers remain in the common event envelope.

Push notifications #

init() never opens the notification permission prompt. When permission is already authorized or provisional, it silently obtains the FCM token and registers it with Adstart. A missing Firebase configuration, a null token, or a registration failure does not make a successful session_started fail.

Ask for permission only from an explicit user action:

await adstart.requestPushPermission();

Call init() first so the registration can reuse the SDK's persistent deviceId and configured hashedId. The token is sent to POST https://events.adstart.cloud/v1/app-push/register together with the Firebase appId. Authorized and provisional results are registered. Denied and not-determined results are not registered.

The SDK observes FirebaseMessaging.onTokenRefresh and synchronizes new tokens. It stores only a SHA-256 token fingerprint for deduplication, never the complete token, and debug logs never include the complete token. Call dispose() when the SDK is no longer used so the refresh listener is canceled.

To delete the token from the local Firebase installation:

await adstart.disablePushNotifications();

In version 0.0.8 this method only calls FirebaseMessaging.deleteToken(). It does not call a backend revoke endpoint.

Receiving and opening push notifications #

Pass an optional onPushEvent callback to init() to receive typed push events. AdstartPushEventType.received is emitted for messages observed while the app is in the foreground. The SDK does not display these messages; the app owns any foreground notification UI, Android notification channels, icons, and iOS presentation options. The normalized event.notification contains the optional title and body needed for foreground presentation, while event.data contains the custom FCM data fields.

AdstartPushEventType.opened is emitted when the user opens a notification from the background or launches the app by opening it from the terminated state. Openings without a deep link are still emitted with deepLink == null. The SDK extracts an absolute URI from the adstart_deep_link data field but never navigates or opens it. The integrating app must validate that the URI is an allowed destination before forwarding it to its router.

Use these optional FCM data fields:

{
  "adstart_message_id": "unique-message-id",
  "adstart_deep_link": "posthaus://product/123"
}

adstart_message_id is preferred for deduplicating openings. If it is absent, the SDK uses the Firebase message ID and then a fingerprint of the message data.

Background or terminated delivery does not guarantee a received callback. In those states Android and iOS can display a notification payload without running the main Flutter isolate. This version does not install a global FirebaseMessaging.onBackgroundMessage handler. Delivery of data-only background messages is platform-dependent and outside this callback contract.

Call dispose() when the SDK is no longer used. It cancels the foreground, opening, and token refresh listeners.

Custom events #

Use trackCustomEvent for business events that are not part of the SDK's built-in event catalog. The eventKey is required, must start with a lowercase letter, may contain only lowercase letters, numbers, and underscores, and may contain at most 64 characters. Built-in Adstart event names are reserved.

eventParams is optional and defaults to an empty JSON object. Its encoded JSON must not exceed 64 KiB in UTF-8.

Screen engagement #

Flutter does not expose a reliable global definition of a page or its scroll depth. The application must measure engagement for each native screen and call trackTimeOnPage with the elapsed whole seconds (from 1 through 1800) and trackScrollDepth with a percentage (from 0 through 100). The web tracker uses the 25, 50, 75, and 100 percent milestones.

Content rendered inside a WebView has its own document lifecycle and scroll position. Measure it in the web content and forward the resulting seconds or depth to these methods; the SDK does not install global navigation, scroll, or WebView listeners.

0
likes
0
points
298
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter SDK for Adstart event collection.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

crypto, firebase_core, firebase_messaging, flutter, http, shared_preferences, uuid

More

Packages that depend on adstart_flutter_sdk