guidexr_optimize_flutter_sdk 0.2.1
guidexr_optimize_flutter_sdk: ^0.2.1 copied to clipboard
Official Flutter SDK for the GuideXR Optimize platform — event tracking, user and device registration, and attribution capture.
example/lib/main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:guidexr_optimize_flutter_sdk/guidexr_optimize_flutter_sdk.dart';
/// Runnable demo of every module documented in the package README.
/// Wire your own [OptimizeConfig] baseUrl/apiKey/channelId before running
/// against a real backend — this points at a placeholder endpoint.
final navigatorKey = GlobalKey<NavigatorState>();
/// Simple event log so the demo UI can show what the SDK is doing —
/// wired to [OptimizeConfig.onLog]/[OptimizeConfig.onError].
final log = ValueNotifier<List<String>>([]);
void addLog(String message) {
log.value = [...log.value, message];
}
/// A no-op forwarder demonstrating the [OptimizeForwarder] shape a real
/// app would implement for Firebase/Meta/etc. — see the README's
/// "Destinations" section. Always ready, just logs what it receives.
class DemoForwarder implements OptimizeForwarder {
@override
bool get isReady => true;
@override
Future<void> onEvent(OptimizeEvent event) async {
addLog('[DemoForwarder] onEvent: ${event.name} (${event.type.name})');
}
@override
Future<void> onIdentify(OptimizeIdentity identity) async {
addLog('[DemoForwarder] onIdentify: ${identity.externalId}');
}
@override
Future<void> onReset() async {
addLog('[DemoForwarder] onReset');
}
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await GuidexrOptimize.init(OptimizeConfig(
baseUrl: 'https://optimize.example.com', // your Optimize endpoint
apiKey: 'YOUR_API_KEY',
channelId: 'YOUR_CHANNEL_ID',
source: 'example_app',
enableLogging: kDebugMode,
navigatorKey: navigatorKey,
onLog: addLog,
onError: (e, stack) => addLog('ERROR: $e'),
onDeepLink: (link) => addLog('deeplink: $link'),
));
// Demonstrates the forwarder pattern without pulling in Firebase/Meta.
GuidexrOptimize.instance.addForwarder('demo', DemoForwarder());
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GuideXR Optimize Example',
navigatorKey: navigatorKey,
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final sdk = GuidexrOptimize.instance;
bool _registered = false;
@override
void initState() {
super.initState();
sdk.trackPageView('home_page');
sdk.trackAppOpen(openSource: OptimizeOpenSource.direct);
sdk.inApp.evaluatePending();
}
Future<void> _registerUser() async {
await sdk.registerUser(
externalId: 'demo-user-1',
profile: const OptimizeProfile(email: 'demo@example.com', firstName: 'Demo'),
channelPreferences: {'push_opt_in': true},
);
sdk.setDefaultEventAttributes({'user_phone': '+10000000000'});
setState(() => _registered = true);
}
Future<void> _registerDevice() async {
await sdk.registerDevice(fcmToken: 'demo-fcm-token', pushEnabled: true);
}
Future<void> _logout() async {
await sdk.reset();
setState(() => _registered = false);
}
Future<void> _setConsent() async {
await sdk.setConsent(const OptimizeConsent(
analytics: true,
marketing: true,
location: false,
version: 'v1',
source: 'example_app',
));
}
Future<void> _listInbox() async {
final page = await sdk.inbox.list(page: 1, pageSize: 10);
addLog('inbox: ${page.notifications.length} of ${page.total} notifications');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('GuideXR Optimize Example')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton(
onPressed: () => sdk.trackClick(
'example_button_click',
attributes: {'from': 'home'},
),
child: const Text('Track click'),
),
ElevatedButton(
onPressed: () => sdk.trackCustom('example_custom_event'),
child: const Text('Track custom event'),
),
ElevatedButton(
onPressed: () => sdk.trackBackendOnly('example_backend_only'),
child: const Text('Track backend-only'),
),
ElevatedButton(
onPressed: _registered ? null : _registerUser,
child: const Text('Register user'),
),
ElevatedButton(
onPressed: _registered ? _registerDevice : null,
child: const Text('Register device'),
),
ElevatedButton(
onPressed: _registered ? _logout : null,
child: const Text('Log out (reset)'),
),
ElevatedButton(
onPressed: _setConsent,
child: const Text('Set consent'),
),
ElevatedButton(
onPressed: _listInbox,
child: const Text('List inbox'),
),
ElevatedButton(
onPressed: sdk.flushQueue,
child: const Text('Flush offline queue'),
),
],
),
),
const Divider(height: 1),
Expanded(
child: ValueListenableBuilder<List<String>>(
valueListenable: log,
builder: (context, entries, _) => ListView.builder(
reverse: true,
padding: const EdgeInsets.all(12),
itemCount: entries.length,
itemBuilder: (context, i) => Text(
entries[entries.length - 1 - i],
style: const TextStyle(fontFamily: 'monospace', fontSize: 12),
),
),
),
),
],
),
);
}
}