Skip to content

Commit

Permalink
Merge pull request #79 from EPNW/ping
Browse files Browse the repository at this point in the history
Ping implementation
  • Loading branch information
TesteurManiak committed May 14, 2023
2 parents 3dae32c + 24500b6 commit 588ec55
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 21 deletions.
76 changes: 59 additions & 17 deletions lib/src/matomo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,25 @@ class MatomoTracker {
final queue = Queue<MatomoEvent>();

@visibleForTesting
late Timer timer;
late Timer dequeueTimer;

@visibleForTesting
Timer? pingTimer;

late sync.Lock _lock;

String? _tokenAuth;

String? get getAuthToken => _tokenAuth;

late final int _dequeueInterval;
late final Duration _dequeueInterval;

late final Duration? _pingInterval;

late bool _newVisit;

MatomoEvent? _lastPageView;

/// Initialize the tracker.
///
/// This method must be called before any other method. Otherwise they might
Expand All @@ -140,14 +147,20 @@ class MatomoTracker {
/// 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](https://github.com/Floating-Dartists/matomo-tracker/issues/78).
/// To deactivate pings, set this to `null`. The default value is a good
/// compromise between accuracy and network traffic.
Future<void> initialize({
required int siteId,
required String url,
bool newVisit = true,
String? visitorId,
String? uid,
String? contentBaseUrl,
int dequeueInterval = 10,
Duration dequeueInterval = const Duration(seconds: 10),
Duration? pingInterval = const Duration(seconds: 30),
String? tokenAuth,
LocalStorage? localStorage,
PackageInfo? packageInfo,
Expand All @@ -174,6 +187,7 @@ class MatomoTracker {
this.url = url;
this.customHeaders = customHeaders;
_dequeueInterval = dequeueInterval;
_pingInterval = pingInterval;
_lock = sync.Lock();
_platformInfo = platformInfo ?? PlatformInfo.instance;
_cookieless = cookieless;
Expand Down Expand Up @@ -242,9 +256,15 @@ class MatomoTracker {
);
_initialized = true;

timer = Timer.periodic(Duration(seconds: _dequeueInterval), (_) {
dequeueTimer = Timer.periodic(_dequeueInterval, (_) {
_dequeue();
});

if (pingInterval != null) {
pingTimer = Timer.periodic(pingInterval, (_) {
_ping();
});
}
}

@visibleForTesting
Expand Down Expand Up @@ -303,20 +323,31 @@ class MatomoTracker {
/// Cancel the timer which checks the queued events to send. (This will not
/// clear the queue.)
void dispose() {
timer.cancel();
pingTimer?.cancel();
dequeueTimer.cancel();
log.clearListeners();
}

// Pause tracker
void pause() {
timer.cancel();
pingTimer?.cancel();
_ping();
dequeueTimer.cancel();
_dequeue();
}

// Resume tracker
void resume() {
if (!timer.isActive) {
timer = Timer.periodic(Duration(seconds: _dequeueInterval), (timer) {
final pingInterval = _pingInterval;
if (pingInterval != null) {
if (!(pingTimer?.isActive ?? false)) {
pingTimer = Timer.periodic(pingInterval, (_) {
_ping();
});
}
}
if (!dequeueTimer.isActive) {
dequeueTimer = Timer.periodic(_dequeueInterval, (timer) {
_dequeue();
});
}
Expand Down Expand Up @@ -393,16 +424,16 @@ class MatomoTracker {
}

validateDimension(dimensions);
return _track(
MatomoEvent(
tracker: this,
action: actionName,
path: path,
campaign: campaign,
dimensions: dimensions,
screenId: pvId ?? randomAlphaNumeric(6),
),
final lastPageView = MatomoEvent(
tracker: this,
action: actionName,
path: path,
campaign: campaign,
dimensions: dimensions,
screenId: pvId ?? randomAlphaNumeric(6),
);
_lastPageView = lastPageView;
return _track(lastPageView);
}

/// Tracks a conversion for a goal.
Expand Down Expand Up @@ -582,6 +613,17 @@ class MatomoTracker {
queue.add(ev);
}

void _ping() {
final lastPageView = _lastPageView;
if (lastPageView != null) {
_track(
lastPageView.copyWith(
ping: true,
),
);
}
}

FutureOr<void> _dequeue() {
if (!_initialized) {
throw const UninitializedMatomoInstanceException();
Expand Down
8 changes: 8 additions & 0 deletions lib/src/matomo_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class MatomoEvent {
this.campaign,
this.dimensions,
this.newVisit,
this.ping,
}) :
// we use clock.now instead of DateTime.now to make testing easier
_date = clock.now().toUtc(),
Expand Down Expand Up @@ -82,6 +83,8 @@ class MatomoEvent {

final bool? newVisit;

final bool? ping;

MatomoEvent copyWith({
MatomoTracker? tracker,
String? path,
Expand All @@ -103,6 +106,7 @@ class MatomoEvent {
Campaign? campaign,
Map<String, String>? dimensions,
bool? newVisit,
bool? ping,
}) =>
MatomoEvent(
tracker: tracker ?? this.tracker,
Expand All @@ -125,6 +129,7 @@ class MatomoEvent {
campaign: campaign ?? this.campaign,
dimensions: dimensions ?? this.dimensions,
newVisit: newVisit ?? this.newVisit,
ping: ping ?? this.ping,
);

Map<String, String> toMap() {
Expand Down Expand Up @@ -157,6 +162,7 @@ class MatomoEvent {
final locale = PlatformDispatcher.instance.locale;
final country = locale.countryCode;
final nV = newVisit;
final p = ping;

return {
// Required parameters
Expand All @@ -165,6 +171,8 @@ class MatomoEvent {

if (nV != null && nV) 'new_visit': '1',

if (p != null && p) 'ping': '1',

// Recommended parameters
if (actionName != null) 'action_name': actionName,
'url': url,
Expand Down
1 change: 1 addition & 0 deletions test/ressources/mock/data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const matomoCampaignGroup = 'group';
const matomoCampaignPlacement = 'placement';
const matomoNewVisit = false;
const matomoChangedNewVisit = true;
const matomoPing = false;
const matomoEventPath = 'path';
const matomoEventAction = 'action';
const matomoEventCategory = 'eventCategory';
Expand Down
3 changes: 3 additions & 0 deletions test/src/matomo_event_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void main() {
taxAmount: matomoTaxAmount,
trackingOrderItems: matomoTrackingOrderItems,
newVisit: matomoNewVisit,
ping: matomoPing,
);
}

Expand Down Expand Up @@ -265,6 +266,7 @@ void main() {
unchangedCopy.trackingOrderItems,
);
expect(matomotoEvent.newVisit, unchangedCopy.newVisit);
expect(matomotoEvent.ping, unchangedCopy.ping);
});
});

Expand Down Expand Up @@ -307,6 +309,7 @@ void main() {
changedCopy.trackingOrderItems,
);
expect(matomoChangedNewVisit, changedCopy.newVisit);
expect(matomotoEvent.ping, changedCopy.ping);
});
});
});
Expand Down
12 changes: 8 additions & 4 deletions test/src/matomo_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ void main() {
(tracker, _) => expect(tracker.url, matomoTrackerUrl),
(tracker, _) => expect(tracker.siteId, matomoTrackerSiteId),
(tracker, _) => expect(tracker.initialized, true),
(tracker, _) => expect(tracker.timer.isActive, true),
(tracker, _) => expect(tracker.dequeueTimer.isActive, true),
(tracker, _) => expect(tracker.pingTimer?.isActive, true),
(tracker, fixedDateTime) =>
expect(tracker.session.firstVisit, fixedDateTime.toUtc()),
(tracker, fixedDateTime) =>
Expand Down Expand Up @@ -107,22 +108,25 @@ void main() {
final matomoTracker = await getInitializedMatomoTracker();
matomoTracker.dispose();

expect(matomoTracker.timer.isActive, false);
expect(matomoTracker.dequeueTimer.isActive, false);
expect(matomoTracker.pingTimer?.isActive, false);
});

test('it should be able to pause', () async {
final matomoTracker = await getInitializedMatomoTracker();
matomoTracker.pause();

expect(matomoTracker.timer.isActive, false);
expect(matomoTracker.dequeueTimer.isActive, false);
expect(matomoTracker.pingTimer?.isActive, false);
});

test('it should be able to resume', () async {
final matomoTracker = await getInitializedMatomoTracker();
matomoTracker
..pause()
..resume();
expect(matomoTracker.timer.isActive, true);
expect(matomoTracker.dequeueTimer.isActive, true);
expect(matomoTracker.pingTimer?.isActive, true);
});

test('it should be able to clear localData', () async {
Expand Down

0 comments on commit 588ec55

Please sign in to comment.