-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(deriv_auth): add log in user tracking events. (#620)
- Loading branch information
1 parent
b0b66da
commit ae9556c
Showing
16 changed files
with
537 additions
and
8 deletions.
There are no files selected for viewing
164 changes: 164 additions & 0 deletions
164
packages/deriv_auth/lib/core/analytics/data/auth_tracking_data.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import 'package:deriv_auth/core/analytics/enums.dart'; | ||
|
||
/// Get user tracking data. | ||
Map<String, dynamic> getUserTrackingData( | ||
LoginAction action, | ||
String appId, { | ||
LoginProvider? provider, | ||
String? errorMessage, | ||
}) => | ||
switch (action) { | ||
LoginAction.openLoginForm => <String, dynamic>{ | ||
'event': 'open', | ||
'properties': <String, String>{ | ||
'app_id': appId, | ||
}, | ||
}, | ||
LoginAction.startLogin => _getLoginStartedTrackingData( | ||
provider, | ||
appId, | ||
), | ||
LoginAction.finishLogin => _getLoginFinishedTrackingData( | ||
provider, | ||
appId, | ||
), | ||
LoginAction.loginError => _getLoginErrorTrackingData( | ||
provider, | ||
appId, | ||
errorMessage ?? (throw Exception('Error message is required.')), | ||
), | ||
}; | ||
|
||
/// Get login started tracking data. | ||
Map<String, dynamic> _getLoginStartedTrackingData( | ||
LoginProvider? provider, String appId) => | ||
switch (provider) { | ||
LoginProvider.email => <String, dynamic>{ | ||
'event': 'login_started', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'email', | ||
}, | ||
}, | ||
LoginProvider.passkey => <String, dynamic>{ | ||
'event': 'login_started', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'passkey', | ||
}, | ||
}, | ||
LoginProvider.google => <String, dynamic>{ | ||
'event': 'login_started', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'google', | ||
}, | ||
}, | ||
LoginProvider.facebook => <String, dynamic>{ | ||
'event': 'login_started', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'facebook', | ||
}, | ||
}, | ||
LoginProvider.apple => <String, dynamic>{ | ||
'event': 'login_started', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'apple', | ||
}, | ||
}, | ||
null => throw Exception('Null LoginProvider is being passed.'), | ||
}; | ||
|
||
/// Get login finished tracking data. | ||
Map<String, dynamic> _getLoginFinishedTrackingData( | ||
LoginProvider? provider, String appId) => | ||
switch (provider) { | ||
LoginProvider.email => <String, dynamic>{ | ||
'event': 'login_finished', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'email', | ||
}, | ||
}, | ||
LoginProvider.passkey => <String, dynamic>{ | ||
'event': 'login_finished', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'passkey', | ||
}, | ||
}, | ||
LoginProvider.google => <String, dynamic>{ | ||
'event': 'login_finished', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'google', | ||
}, | ||
}, | ||
LoginProvider.facebook => <String, dynamic>{ | ||
'event': 'login_finished', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'facebook', | ||
}, | ||
}, | ||
LoginProvider.apple => <String, dynamic>{ | ||
'event': 'login_finished', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'apple', | ||
}, | ||
}, | ||
null => throw Exception('Null LoginProvider is being passed.'), | ||
}; | ||
|
||
/// Get login error tracking data. | ||
Map<String, dynamic> _getLoginErrorTrackingData( | ||
LoginProvider? provider, | ||
String appId, | ||
String errorMessage, | ||
) => | ||
switch (provider) { | ||
LoginProvider.email => <String, dynamic>{ | ||
'event': 'login_flow_error', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'email', | ||
'error_message': errorMessage, | ||
}, | ||
}, | ||
LoginProvider.passkey => <String, dynamic>{ | ||
'event': 'login_flow_error', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'passkey', | ||
'error_message': errorMessage, | ||
}, | ||
}, | ||
LoginProvider.google => <String, dynamic>{ | ||
'event': 'login_flow_error', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'google', | ||
'error_message': errorMessage, | ||
}, | ||
}, | ||
LoginProvider.facebook => <String, dynamic>{ | ||
'event': 'login_flow_error', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'facebook', | ||
'error_message': errorMessage, | ||
}, | ||
}, | ||
LoginProvider.apple => <String, dynamic>{ | ||
'event': 'login_flow_error', | ||
'properties': <String, dynamic>{ | ||
'app_id': appId, | ||
'login_provider': 'apple', | ||
'error_message': errorMessage, | ||
}, | ||
}, | ||
null => throw Exception('Null LoginProvider is being passed.'), | ||
}; |
131 changes: 131 additions & 0 deletions
131
packages/deriv_auth/lib/core/analytics/data/auth_tracking_repository.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import 'package:analytics/sdk/rudderstack/sdk/deriv_rudderstack_sdk.dart'; | ||
import 'package:deriv_auth/core/services/token/models/enums.dart'; | ||
import 'package:deriv_auth/core/analytics/data/auth_tracking_data.dart'; | ||
import 'package:deriv_auth/core/analytics/domain/auth_user_tracking_interface.dart'; | ||
import 'package:deriv_auth/core/analytics/enums.dart'; | ||
|
||
/// Repository to track user events. | ||
class AuthTrackingRepository implements AuthUserTrackingInterface { | ||
/// Constructor for [AnalyticsRepository]. | ||
AuthTrackingRepository._( | ||
this._appId, | ||
this._derivRudderstack, | ||
); | ||
|
||
static AuthTrackingRepository? _instance; | ||
|
||
/// Singleton instance of [AnalyticsRepository]. | ||
static AuthTrackingRepository get instance => _instance ??= | ||
throw Exception('AuthTrackingRepository is not initialized'); | ||
|
||
/// Instance of [DerivRudderstack]. | ||
final DerivRudderstack _derivRudderstack; | ||
|
||
/// Initialize [AnalyticsRepository]. | ||
static void init( | ||
String appId, { | ||
required DerivRudderstack derivRudderstack, | ||
}) => | ||
_instance = AuthTrackingRepository._( | ||
appId, | ||
derivRudderstack, | ||
); | ||
|
||
/// Deriv client app ID. | ||
final String _appId; | ||
|
||
LoginProvider? _loginProvider; | ||
|
||
@override | ||
void trackUserOpenedLoginForm() { | ||
final Map<String, dynamic> data = getUserTrackingData( | ||
LoginAction.openLoginForm, | ||
_appId, | ||
); | ||
|
||
_derivRudderstack.track( | ||
eventName: data['event'] as String, | ||
properties: data['properties'] as Map<String, dynamic>, | ||
); | ||
} | ||
|
||
@override | ||
void trackError(String errorMessage) { | ||
final Map<String, dynamic> data = getUserTrackingData( | ||
LoginAction.loginError, | ||
_appId, | ||
errorMessage: errorMessage, | ||
); | ||
|
||
_derivRudderstack.track( | ||
eventName: data['event'] as String, | ||
properties: data['properties'] as Map<String, dynamic>, | ||
); | ||
} | ||
|
||
@override | ||
void trackSystemLoginPressed() { | ||
final Map<String, dynamic> data = getUserTrackingData( | ||
LoginAction.startLogin, | ||
_appId, | ||
provider: LoginProvider.email, | ||
); | ||
|
||
_loginProvider = LoginProvider.email; | ||
|
||
_derivRudderstack.track( | ||
eventName: data['event'] as String, | ||
properties: data['properties'] as Map<String, dynamic>, | ||
); | ||
} | ||
|
||
@override | ||
void trackPasskeyLoginPressed() { | ||
final Map<String, dynamic> data = getUserTrackingData( | ||
LoginAction.startLogin, | ||
_appId, | ||
provider: LoginProvider.passkey, | ||
); | ||
|
||
_loginProvider = LoginProvider.passkey; | ||
|
||
_derivRudderstack.track( | ||
eventName: data['event'] as String, | ||
properties: data['properties'] as Map<String, dynamic>, | ||
); | ||
} | ||
|
||
@override | ||
void trackSocialLoginPressed(SocialAuthProvider type) { | ||
_loginProvider = switch (type) { | ||
SocialAuthProvider.google => LoginProvider.google, | ||
SocialAuthProvider.facebook => LoginProvider.facebook, | ||
SocialAuthProvider.apple => LoginProvider.apple, | ||
}; | ||
|
||
final Map<String, dynamic> data = getUserTrackingData( | ||
LoginAction.startLogin, | ||
_appId, | ||
provider: _loginProvider, | ||
); | ||
|
||
_derivRudderstack.track( | ||
eventName: data['event'] as String, | ||
properties: data['properties'] as Map<String, dynamic>, | ||
); | ||
} | ||
|
||
@override | ||
void trackLoginFinished() { | ||
final Map<String, dynamic> data = getUserTrackingData( | ||
LoginAction.finishLogin, | ||
_appId, | ||
provider: _loginProvider, | ||
); | ||
|
||
_derivRudderstack.track( | ||
eventName: data['event'] as String, | ||
properties: data['properties'] as Map<String, dynamic>, | ||
); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
packages/deriv_auth/lib/core/analytics/domain/auth_user_tracking_interface.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import 'package:deriv_auth/deriv_auth.dart'; | ||
|
||
/// Interface to define the methods for tracking user events. | ||
abstract interface class AuthUserTrackingInterface { | ||
/// Track user opened login form. | ||
void trackUserOpenedLoginForm(); | ||
|
||
/// Track user clicks log after entering email and password. | ||
void trackSystemLoginPressed(); | ||
|
||
/// Track user clicks on Passkey login button. | ||
void trackPasskeyLoginPressed(); | ||
|
||
/// Track user clicks on social login button. | ||
void trackSocialLoginPressed( | ||
SocialAuthProvider type, | ||
); | ||
|
||
/// Track login finished. | ||
void trackLoginFinished(); | ||
|
||
/// Track login error. | ||
void trackError(String errorMessage); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/// Enum for login actions | ||
enum LoginAction { | ||
/// Open login form. | ||
openLoginForm, | ||
|
||
/// Start system login. | ||
startLogin, | ||
|
||
/// Finish login. | ||
finishLogin, | ||
|
||
/// Login error. | ||
loginError, | ||
} | ||
|
||
/// Enum for login provider. | ||
enum LoginProvider { | ||
/// Email login. | ||
email, | ||
|
||
/// Passkey login. | ||
passkey, | ||
|
||
/// Google login. | ||
google, | ||
|
||
/// Facebook login. | ||
facebook, | ||
|
||
/// Apple login. | ||
apple, | ||
} |
36 changes: 36 additions & 0 deletions
36
packages/deriv_auth/lib/core/analytics/service/auth_tracking_mixin.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import 'package:deriv_auth/deriv_auth.dart'; | ||
import 'package:deriv_auth/core/analytics/data/auth_tracking_repository.dart'; | ||
|
||
/// Mixin for tracking user authentication actions. | ||
mixin AuthTrackingMixin { | ||
late final AuthTrackingRepository _repository = | ||
AuthTrackingRepository.instance; | ||
|
||
/// Track user opened login form. | ||
void trackUserOpenedLoginForm() => _repository.trackUserOpenedLoginForm(); | ||
|
||
/// Track login error. | ||
void trackError(String errorMessage) => _repository.trackError(errorMessage); | ||
|
||
/// Track login started. | ||
void trackLoginWithEmailAndPassword() => | ||
_repository.trackSystemLoginPressed(); | ||
|
||
/// Track Passkey login started. | ||
void trackLoginWithPasskey() => _repository.trackPasskeyLoginPressed(); | ||
|
||
/// Track Google login started. | ||
void trackLoginWithGoogle() => | ||
_repository.trackSocialLoginPressed(SocialAuthProvider.google); | ||
|
||
/// Track Facebook login started. | ||
void trackLoginWithFacebook() => | ||
_repository.trackSocialLoginPressed(SocialAuthProvider.facebook); | ||
|
||
/// Track Apple login started. | ||
void trackLoginWithApple() => | ||
_repository.trackSocialLoginPressed(SocialAuthProvider.apple); | ||
|
||
/// Track login finished. | ||
void trackLoginFinished() => _repository.trackLoginFinished(); | ||
} |
Oops, something went wrong.