Docs

Initialize

Start the SDK once, before runApp, with a publishable key.

Call initialize before runApp

lib/main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:lander_flutter/lander_flutter.dart';

Future<void> main() async {
  await Lander.initialize(
    apiKey: 'pk_live_...', // publishable key from Settings > API keys
    enableLogging: kDebugMode,
  );
  runApp(const MyApp());
}

initialize calls WidgetsFlutterBinding.ensureInitialized() for you, so you do not need to call it first.

Awaiting initialize is fast. It only waits for local work: loading (or creating) the install ID from on device storage and asking the native side for the launch link. The launch report to Lander (POST /v1/sdk/init) runs in the background, so a slow or missing network never delays your first frame.

Parameters

static Future<void> initialize({
  required String apiKey,
  String baseUrl = 'https://api.golander.link',
  bool enableLogging = false,
})

Prop

Type

Use a publishable key

Create keys in the dashboard under Settings > API keys (Dashboard: API keys). Only publishable keys are accepted:

KeyIn an app?
pk_test_...Yes. Test environment.
pk_live_...Yes. Live environment.
sk_test_..., sk_live_...Never. initialize throws an ArgumentError.

Anything you ship in an app binary is public, which is why secret keys are refused outright. Any other value that does not start with pk_ also throws an ArgumentError.

Test and live builds

The key you pass decides which environment the app talks to. Links created in the test environment only resolve for apps using a pk_test_ key, and live links only for pk_live_ keys. See Environments.

A simple way to switch is a compile time define:

lib/main.dart
const landerKey = String.fromEnvironment('LANDER_KEY');

Future<void> main() async {
  await Lander.initialize(apiKey: landerKey, enableLogging: kDebugMode);
  runApp(const MyApp());
}
flutter run --dart-define=LANDER_KEY=pk_test_...
flutter build ipa --dart-define=LANDER_KEY=pk_live_...

If you forget the define, the key is an empty string and initialize throws an ArgumentError, so the mistake shows up on the first run instead of in production.

If you switch an existing install from a test key to a live key (or to another project), Lander reports that the install ID belongs elsewhere (install_id_conflict). The SDK then creates a fresh install ID and reports a first launch, so nothing breaks.

What initialize does

  1. Validates the key (throws ArgumentError for secret or malformed keys).
  2. Loads the install ID from storage, or creates a random UUID v4 on first launch.
  3. Reads the launch link from the native side and starts listening for links that arrive later.
  4. In the background, reports the launch with POST /v1/sdk/init. On an Android first launch it reads the Play Install Referrer (waiting at most 5 seconds) and sends it along. On a first launch the answer may carry a deferred link.
  5. Loads any events left in the on device queue from earlier sessions and sends them.

initialize never throws because of the network. A failed launch report is logged (when logging is on). A failed first launch report is retried on the next launch with the same idempotency key, so the install is counted once.

Rules worth knowing

  • Call it once. A second call is ignored (it logs a message when logging is on) and returns the same future as the first.
  • Other methods need it. getInitialLink, createLink, claimHandoff and trackEvent throw a StateError if you call them before initialize.
  • onDeepLink does not. You can listen to Lander.onDeepLink before initialize; links are buffered until you do.
  • installId is null until initialize completes.

The install ID

Lander.installId is the random UUID v4 the SDK created for this install. It is not tied to the device or the user:

  • It is stored in a file excluded from iCloud and Android backups (Application Support on iOS, noBackupFilesDir on Android), so it is never restored onto another device.
  • It is gone when the app is uninstalled. A reinstall gets a new one.

It is handy for support requests: show it in a debug screen so testers can quote it.

Text('Install ID: ${Lander.installId ?? '(loading)'}')

Next steps

On this page