flutter_estatisticas 0.2.2
flutter_estatisticas: ^0.2.2 copied to clipboard
A Flutter package for integrating Umami Analytics into your apps. Track navigation and custom events easily, providing privacy-friendly analytics for your users.
Flutter Umami Analytics Integration #
A comprehensive Flutter package that integrates Umami Analytics into your Flutter app. This package provides both tracking capabilities (pageviews and custom events) and full REST API management for websites, users, teams, and analytics data.
🚀 Features #
- 📊 Event Tracking: Automatic navigation tracking and custom events
- 🔐 Authentication: Login and token management for self-hosted Umami
- 👥 User Management: Create, update, delete users and manage permissions
- 🏢 Team Management: Team creation, user roles, and collaboration
- 🌐 Website Management: Website CRUD operations and analytics
- 📈 Analytics Data: Retrieve pageviews, events, sessions, and metrics
- ☁️ Umami Cloud Support: Works with both self-hosted and Umami Cloud
- 🔒 No-Auth Tracking: Send events without authentication using
/api/send
📦 Installation #
Add to your pubspec.yaml:
dependencies:
flutter_estatisticas: ^0.2.2
Then run:
flutter pub get
🎯 Quick Start #
1. Basic Event Tracking (No Authentication Required) #
Perfect for simple analytics tracking without managing authentication.
import 'package:flutter_estatisticas/umami_service.dart';
import 'package:flutter_estatisticas/umami_navigation_observer.dart';
// Instantiate the service
final umamiService = UmamiService(
endpoint: 'https://cloud.umami.is', // Umami Cloud or your endpoint
website: 'your-website-id', // Website ID from Umami dashboard
hostname: 'your-app.com', // Your app's identifier
);
// Add to MaterialApp for automatic navigation tracking
MaterialApp(
navigatorObservers: [
UmamiNavigationObserver(umamiService),
],
// ... rest of your app
)
// Send custom events
umamiService.enviarClique(
context,
'Home Page',
'subscribe_button',
);
umamiService.enviarEvento(
context,
title: 'Settings',
name: 'theme_changed',
data: {'theme': 'dark'},
);
2. Advanced Analytics with REST API #
For complete control over your Umami instance, including user and website management.
import 'package:flutter_estatisticas/services/umami_auth_service.dart';
import 'package:flutter_estatisticas/services/umami_website_service.dart';
final authService = UmamiAuthService(
endpoint: 'https://your-umami-instance.com'
);
final websiteService = UmamiWebsiteService(
endpoint: 'https://your-umami-instance.com'
);
// Login (self-hosted only)
final loginResponse = await authService.login(
username: 'admin',
password: 'password',
);
final token = loginResponse?['token'];
// Get website analytics
final stats = await websiteService.getWebsiteStats(
token: token!,
websiteId: 'website-id',
startAt: DateTime.now().subtract(Duration(days: 7)).millisecondsSinceEpoch,
endAt: DateTime.now().millisecondsSinceEpoch,
);
📋 Available Services #
🔐 Authentication Service (UmamiAuthService) #
final authService = UmamiAuthService(endpoint: 'https://your-endpoint.com');
// Login
final response = await authService.login(
username: 'admin',
password: 'password',
);
// Verify token
final isValid = await authService.isTokenValid(token);
👥 User Management (UmamiUserService) #
final userService = UmamiUserService(endpoint: 'https://your-endpoint.com');
// Create user
final user = await userService.createUser(
token: token,
username: 'newuser',
password: 'password',
role: 'user', // 'admin', 'user', or 'view-only'
);
// Get all users (admin only)
final users = await userService.getAllUsers(token: token);
// Get user websites
final websites = await userService.getUserWebsites(
token: token,
userId: 'user-id',
);
🏢 Team Management (UmamiTeamService) #
final teamService = UmamiTeamService(endpoint: 'https://your-endpoint.com');
// Create team
final team = await teamService.createTeam(
token: token,
name: 'Development Team',
);
// Add user to team
await teamService.addUserToTeam(
token: token,
teamId: 'team-id',
userId: 'user-id',
role: 'team-member', // 'team-owner', 'team-manager', 'team-member', 'team-view-only'
);
// Get team websites
final websites = await teamService.getTeamWebsites(
token: token,
teamId: 'team-id',
);
🌐 Website Management (UmamiWebsiteService) #
final websiteService = UmamiWebsiteService(endpoint: 'https://your-endpoint.com');
// Create website
final website = await websiteService.createWebsite(
token: token,
domain: 'myapp.com',
name: 'My Mobile App',
teamId: 'team-id', // optional
);
// Get website statistics
final stats = await websiteService.getWebsiteStats(
token: token,
websiteId: 'website-id',
startAt: DateTime.now().subtract(Duration(days: 30)).millisecondsSinceEpoch,
endAt: DateTime.now().millisecondsSinceEpoch,
);
// Get pageviews over time
final pageviews = await websiteService.getWebsitePageviews(
token: token,
websiteId: 'website-id',
startAt: startTimestamp,
endAt: endTimestamp,
unit: 'day', // 'year', 'month', 'hour', 'day'
timezone: 'Europe/Lisbon',
);
// Get website metrics (pages, referrers, browsers, etc.)
final metrics = await websiteService.getWebsiteMetrics(
token: token,
websiteId: 'website-id',
startAt: startTimestamp,
endAt: endTimestamp,
type: 'url', // 'url', 'referrer', 'browser', 'os', 'device', 'country', 'event'
);
📊 Event Tracking (UmamiEventService) #
final eventService = UmamiEventService(endpoint: 'https://your-endpoint.com');
// Get website events
final events = await eventService.getWebsiteEvents(
token: token,
websiteId: 'website-id',
startAt: startTimestamp,
endAt: endTimestamp,
);
// Get event data with filtering
final filteredEvents = await eventService.getWebsiteEventData(
token: token,
websiteId: 'website-id',
startAt: startTimestamp,
endAt: endTimestamp,
eventType: 'custom',
);
🔄 Session Management (UmamiSessionService) #
final sessionService = UmamiSessionService(endpoint: 'https://your-endpoint.com');
// Get website sessions
final sessions = await sessionService.getWebsiteSessions(
token: token,
websiteId: 'website-id',
startAt: startTimestamp,
endAt: endTimestamp,
);
// Get session activity
final activity = await sessionService.getSessionActivity(
token: token,
websiteId: 'website-id',
startAt: startTimestamp,
endAt: endTimestamp,
unit: 'hour',
timezone: 'UTC',
);
📤 Direct Send Service (UmamiSendService) #
Send events directly without authentication - perfect for public analytics.
final sendService = UmamiSendService(
website: 'website-id',
hostname: 'your-app.com',
endpoint: 'https://cloud.umami.is', // or your self-hosted URL
);
// Send pageview
await sendService.sendPageview(
context: context,
title: 'Home Screen',
url: '/home',
);
// Send custom event
await sendService.sendCustomEvent(
context: context,
title: 'Settings',
url: '/settings',
name: 'toggle_notifications',
data: {'enabled': true},
);
🌟 Usage Examples #
Complete Analytics Dashboard #
class AnalyticsDashboard extends StatefulWidget {
@override
_AnalyticsDashboardState createState() => _AnalyticsDashboardState();
}
class _AnalyticsDashboardState extends State<AnalyticsDashboard> {
final websiteService = UmamiWebsiteService(endpoint: 'https://your-endpoint.com');
String? token;
Map<String, dynamic>? stats;
@override
void initState() {
super.initState();
loadAnalytics();
}
Future<void> loadAnalytics() async {
// Assume token is obtained from authentication
final endTime = DateTime.now();
final startTime = endTime.subtract(Duration(days: 7));
final analyticsData = await websiteService.getWebsiteStats(
token: token!,
websiteId: 'your-website-id',
startAt: startTime.millisecondsSinceEpoch,
endAt: endTime.millisecondsSinceEpoch,
);
setState(() {
stats = analyticsData;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Analytics Dashboard')),
body: stats == null
? CircularProgressIndicator()
: Column(
children: [
Text('Pageviews: ${stats!['pageviews']}'),
Text('Visitors: ${stats!['visitors']}'),
Text('Bounce Rate: ${stats!['bounces']}'),
// Add charts and more detailed analytics
],
),
);
}
}
Multi-User Team Setup #
Future<void> setupTeamAndWebsite() async {
final authService = UmamiAuthService(endpoint: 'https://your-endpoint.com');
final teamService = UmamiTeamService(endpoint: 'https://your-endpoint.com');
final userService = UmamiUserService(endpoint: 'https://your-endpoint.com');
final websiteService = UmamiWebsiteService(endpoint: 'https://your-endpoint.com');
// Login as admin
final loginResponse = await authService.login(
username: 'admin',
password: 'admin-password',
);
final token = loginResponse?['token'];
// Create a team
final team = await teamService.createTeam(
token: token!,
name: 'Mobile Development Team',
);
final teamId = team?[0]['id'];
// Create a user
final user = await userService.createUser(
token: token,
username: 'developer1',
password: 'dev-password',
role: 'user',
);
final userId = user?['id'];
// Add user to team
await teamService.addUserToTeam(
token: token,
teamId: teamId,
userId: userId,
role: 'team-member',
);
// Create website under team
final website = await websiteService.createWebsite(
token: token,
domain: 'myapp.com',
name: 'My Flutter App',
teamId: teamId,
);
print('Setup complete! Website ID: ${website?['websiteUuid']}');
}
🔧 Configuration #
Environment Variables #
For better security, consider using environment variables:
// .env file
UMAMI_ENDPOINT=https://your-umami-instance.com
UMAMI_WEBSITE_ID=your-website-id
UMAMI_USERNAME=admin
UMAMI_PASSWORD=password
// Usage
final endpoint = dotenv.env['UMAMI_ENDPOINT']!;
final websiteId = dotenv.env['UMAMI_WEBSITE_ID']!;
Error Handling #
All services include comprehensive error handling with detailed JSON error responses:
final result = await websiteService.createWebsite(
token: invalidToken,
domain: 'test.com',
name: 'Test Site',
);
if (result == null) {
// Check debug console for detailed error information:
// Failed to create website: 401
// Error JSON: {"message": "Unauthorized"}
}
🌍 Umami Cloud vs Self-Hosted #
| Feature | Umami Cloud | Self-Hosted |
|---|---|---|
| Authentication | API Key | Username/Password |
| User Management | ❌ | ✅ |
| Team Management | ❌ | ✅ |
| Website Management | Limited | ✅ |
| Event Tracking | ✅ | ✅ |
| Analytics Data | ✅ | ✅ |
For Umami Cloud, use the direct send service or API keys. For self-hosted, you have full access to all management features.
📱 Platform Support #
- ✅ Android
- ✅ iOS
- ✅ Web
- ✅ Desktop (Windows, macOS, Linux)
🤝 Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links #
Made with ❤️ for the Flutter community