initialize method
- required int siteId,
- required String url,
- bool newVisit = true,
- String? visitorId,
- String? uid,
- String? contentBaseUrl,
- DispatchSettings dispatchSettings = const DispatchSettings.nonPersistent(),
- Duration? pingInterval = const Duration(seconds: 30),
- String? tokenAuth,
- LocalStorage? localStorage,
- PackageInfo? packageInfo,
- PlatformInfo? platformInfo,
- bool cookieless = false,
- Level verbosityLevel = Level.off,
- Map<
String, String> customHeaders = const {}, - String? userAgent,
- bool attachLastScreenInfo = true,
Initialize the tracker.
This method must be called before any other method. Otherwise they might throw an UninitializedMatomoInstanceException.
If the tracker is already initialized, an AlreadyInitializedMatomoInstanceException will be thrown.
The newVisit
parameter is used to mark this initialization the start
of a new visit. If set to false
it is left to Matomo to decide if this
is a new visit or not. In practice, this will be used as the newVisit
parameter in the first track...
method call but only if the newVisit
parameter in that method call is left to null
.
The visitorId
should have a length of 16 characters otherwise an
ArgumentError will be thrown. This parameter corresponds with the
_id
and should not be confused with the user id uid
. See the
Visitor class for additional remarks. It is recommended to leave this
to null
to use an automatically generated id.
If cookieless
is set to true, a CookielessStorage
instance will be
used. This means that the first_visit and the user_id will be stored in
memory and will be lost when the app is closed.
The pingInterval
is used to set the interval in which pings are
send to Matomo to circumvent the last page viewtime issue.
To deactivate pings, set this to null
. The default value is a good
compromise between accuracy and network traffic.
It is recommended to leave userAgent
to null
so it will be detected
automatically.
Implementation
Future<void> initialize({
required int siteId,
required String url,
bool newVisit = true,
String? visitorId,
String? uid,
String? contentBaseUrl,
DispatchSettings dispatchSettings = const DispatchSettings.nonPersistent(),
Duration? pingInterval = const Duration(seconds: 30),
String? tokenAuth,
LocalStorage? localStorage,
PackageInfo? packageInfo,
PlatformInfo? platformInfo,
bool cookieless = false,
Level verbosityLevel = Level.off,
Map<String, String> customHeaders = const {},
String? userAgent,
bool attachLastScreenInfo = true,
}) async {
if (_initialized) {
throw const AlreadyInitializedMatomoInstanceException();
}
if (visitorId != null && visitorId.length != 16) {
throw ArgumentError.value(
visitorId,
'visitorId',
'The visitorId must be 16 characters long',
);
}
assertDurationNotNegative(
value: dispatchSettings.dequeueInterval,
name: 'dequeueInterval',
);
assertDurationNotNegative(
value: pingInterval,
name: 'pingInterval',
);
log.setLogging(level: verbosityLevel);
this.siteId = siteId;
_url = url;
this.customHeaders = customHeaders;
_pingInterval = pingInterval;
_lock = sync.Lock();
_platformInfo = platformInfo ?? PlatformInfo.instance;
_cookieless = cookieless;
_tokenAuth = tokenAuth;
_newVisit = newVisit;
this.attachLastScreenInfo = attachLastScreenInfo;
_dispatchSettings = dispatchSettings;
final effectiveLocalStorage = localStorage ?? SharedPrefsStorage();
_localStorage = cookieless
? CookielessStorage(storage: effectiveLocalStorage)
: effectiveLocalStorage;
final onLoad = _dispatchSettings.onLoad;
queue = _dispatchSettings.persistentQueue && onLoad != null
? await PersistentQueue.load(
storage: _localStorage,
onLoadFilter: onLoad,
)
: Queue();
final localVisitorId = visitorId ?? await _getVisitorId();
_visitor = Visitor(id: localVisitorId, uid: uid);
// User agent
this.userAgent = userAgent ?? await getUserAgent();
_dispatcher = MatomoDispatcher(
baseUrl: url,
tokenAuth: tokenAuth,
userAgent: this.userAgent,
log: log,
);
// Screen Resolution
final physicalSize = PlatformDispatcher.instance.views.first.physicalSize;
screenResolution = Size(
physicalSize.width,
physicalSize.height,
);
// Initialize Session Information
final now = clock.now().toUtc();
DateTime firstVisit = now;
int visitCount = 1;
final localFirstVisit = await _localStorage.getFirstVisit();
if (localFirstVisit != null) {
firstVisit = localFirstVisit;
} else {
unawaited(_localStorage.setFirstVisit(now));
// Save the visitorId for future visits.
unawaited(_saveVisitorId(localVisitorId));
}
final localVisitorCount = await _localStorage.getVisitCount();
visitCount += localVisitorCount;
unawaited(_localStorage.setVisitCount(visitCount));
session = Session(
firstVisit: firstVisit,
lastVisit: now,
visitCount: visitCount,
);
if (contentBaseUrl != null) {
contentBase = contentBaseUrl;
} else if (kIsWeb) {
contentBase = Uri.base.toString();
} else {
final effectivePackageInfo =
packageInfo ?? await PackageInfo.fromPlatform();
contentBase = 'https://${effectivePackageInfo.packageName}';
}
_optOut = await _localStorage.getOptOut();
unawaited(_localStorage.setOptOut(optOut: _optOut));
log.fine(
'Matomo Initialized: firstVisit=$firstVisit; lastVisit=$now; visitCount=$visitCount; visitorId=$visitorId; contentBase=$contentBase; resolution=${screenResolution.width}x${screenResolution.height}; userAgent=${this.userAgent}',
);
_initialized = true;
dequeueTimer = Timer.periodic(_dispatchSettings.dequeueInterval, (_) {
_dequeue();
});
if (pingInterval != null) {
pingTimer = Timer.periodic(pingInterval, (_) {
_ping();
});
}
if (queue.isNotEmpty) {
await dispatchActions();
}
}