retenshun 1.1.0
retenshun: ^1.1.0 copied to clipboard
Official Retenshun Flutter SDK for event tracking, user identification, and e-commerce analytics.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:retenshun/retenshun.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Retenshun
await Retenshun.init(
projectId: 'cmmjpqioh0002c5esie0h7zte',
apiKey: 'pk_live_vkEoCvW1ADfS8X2rAznZV8uETLFDvdfH',
debug: true,
flushAt: 1, // Flush immediately for testing
flushIntervalSeconds: 5,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return RetenshunProvider(
child: MaterialApp(
title: 'Retenshun Demo',
theme: ThemeData(
colorSchemeSeed: const Color(0xFFC9933E),
brightness: Brightness.dark,
scaffoldBackgroundColor: const Color(0xFF0F2942),
useMaterial3: true,
),
navigatorObservers: [RetenshunObserver()],
home: const HomePage(),
routes: {
'/product': (context) => const ProductPage(),
},
),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isIdentified = false;
void _showSnack(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
duration: const Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
),
);
}
@override
Widget build(BuildContext context) {
final userId = Retenshun.getUserId();
_isIdentified = userId != null;
return Scaffold(
appBar: AppBar(
title: const Text('Retenshun Demo'),
actions: [
if (_isIdentified)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Center(
child: Text(
'User: $userId',
style: const TextStyle(fontSize: 12),
),
),
),
],
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Status
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: _isIdentified ? Colors.green.withValues(alpha: 0.15) : Colors.orange.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: _isIdentified ? Colors.green.withValues(alpha: 0.3) : Colors.orange.withValues(alpha: 0.3),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
_isIdentified ? Icons.check_circle : Icons.person_off,
color: _isIdentified ? Colors.green : Colors.orange,
size: 20,
),
const SizedBox(width: 8),
Text(
_isIdentified ? 'Identified as $userId' : 'Not identified (anonymous)',
style: TextStyle(
color: _isIdentified ? Colors.green : Colors.orange,
),
),
],
),
),
const SizedBox(height: 32),
// Identify user on login
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () {
Retenshun.identify('user_123', properties: {
'email': 'john@example.com',
'name': 'John Doe',
'plan': 'pro',
});
Retenshun.flush();
setState(() => _isIdentified = true);
_showSnack('Identified as user_123 + flushed');
},
icon: const Icon(Icons.login),
label: const Text('Login (Identify)'),
),
),
const SizedBox(height: 12),
// Track custom event
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () {
Retenshun.track('button_clicked', properties: {
'button': 'cta',
'screen': 'home',
});
Retenshun.flush();
_showSnack('Tracked: button_clicked + flushed');
},
icon: const Icon(Icons.touch_app),
label: const Text('Track Event'),
),
),
const SizedBox(height: 12),
// Navigate to product page
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () {
Navigator.pushNamed(context, '/product');
},
icon: const Icon(Icons.shopping_bag),
label: const Text('View Product'),
),
),
const SizedBox(height: 12),
// Manual flush
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: () async {
await Retenshun.flush();
_showSnack('Queue flushed');
},
icon: const Icon(Icons.send),
label: const Text('Flush Queue'),
),
),
const SizedBox(height: 12),
// Logout
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: () {
Retenshun.reset();
setState(() => _isIdentified = false);
_showSnack('User reset (logged out)');
},
icon: const Icon(Icons.logout),
label: const Text('Logout (Reset)'),
style: OutlinedButton.styleFrom(
foregroundColor: Colors.redAccent,
side: const BorderSide(color: Colors.redAccent),
),
),
),
],
),
),
),
);
}
}
class ProductPage extends StatefulWidget {
const ProductPage({super.key});
@override
State<ProductPage> createState() => _ProductPageState();
}
class _ProductPageState extends State<ProductPage> {
void _showSnack(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
duration: const Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
),
);
}
@override
void initState() {
super.initState();
// Track product view
Retenshun.ecommerce.productViewed(
productId: 'prod_1',
name: 'Wireless Headphones',
price: 79.99,
category: 'Electronics',
);
Retenshun.flush();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Product')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.headphones, size: 64),
const SizedBox(height: 16),
const Text(
'Wireless Headphones',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const Text(
'\$79.99',
style: TextStyle(fontSize: 20, color: Color(0xFFC9933E)),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () {
Retenshun.ecommerce.addedToCart(
productId: 'prod_1',
name: 'Wireless Headphones',
price: 79.99,
quantity: 1,
);
Retenshun.flush();
_showSnack('Tracked: added_to_cart + flushed');
},
icon: const Icon(Icons.add_shopping_cart),
label: const Text('Add to Cart'),
),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () {
Retenshun.ecommerce.orderCompleted(
orderId: 'ord_${DateTime.now().millisecondsSinceEpoch}',
total: 79.99,
currency: 'USD',
products: [
{'product_id': 'prod_1', 'quantity': 1, 'price': 79.99},
],
);
Retenshun.flush();
_showSnack('Tracked: order_completed + flushed');
},
icon: const Icon(Icons.payment),
label: const Text('Buy Now'),
),
),
],
),
),
),
);
}
}