Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing Events Immediately After Startup #85

Closed
jakobhec opened this issue Feb 29, 2024 · 20 comments · Fixed by #92
Closed

Missing Events Immediately After Startup #85

jakobhec opened this issue Feb 29, 2024 · 20 comments · Fixed by #92
Labels
question Further information is requested

Comments

@jakobhec
Copy link

Version

4.0.1

Steps to Reproduce

Capture an event very early after the app starts up. For example, here we do it right after WidgetsFlutterBinding.ensureInitialized().

Future<void> main() async {
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  Posthog().capture(eventName: 'dummy_event');
  ...

Expected Result

I would expect all events to show up on my dashboard, regardless of when I capture them in the app's lifecycle.

Actual Result

Events within the first second after the app starts up are not always captured. A rough estimate would be that 90% of the dummy_event in the example above are missed, only 10% appear on my dashboard.

I would expect 100% of the events to appear on my dashboard.

This works for subsequent events (e.g., when I log a button tap on the second screen).

@jakobhec jakobhec added the bug Something isn't working label Feb 29, 2024
@jakobhec jakobhec changed the title Initial events not working Missing Events Immediately After Startup Feb 29, 2024
@marandaneto
Copy link
Member

@jakobhec can you enable the debug option and check the logs? I'd be interested to know if there's anything strange.

@jakobhec
Copy link
Author

@marandaneto It now looks like this:

Future<void> main() async {
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  await Posthog().debug(true);
  Posthog().capture(eventName: 'dummy_event');
  ...

But I cannot see any additional output in my terminal or debug console.

@marandaneto
Copy link
Member

@jakobhec your test is Android or iOS?

@jakobhec
Copy link
Author

@marandaneto iOS

@marandaneto
Copy link
Member

marandaneto commented Feb 29, 2024

Events are sent in batches, it only flushes when the queue is 20 (by default), so if you capture a few more events after, once it is 20, all events are flushed, including the dummy_event, maybe that's the issue you are seeing? like a delay.
I just tested it and it's all working well on my sample.
If that's not the case, can you provide an MRE?

@marandaneto marandaneto added question Further information is requested and removed bug Something isn't working labels Feb 29, 2024
@marandaneto
Copy link
Member

@jakobhec did you check it?

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

@marandaneto Thanks for getting back! I would assume that there is another reason.

I use a single Dart function for logging to Firebase and PostHog, which seems reliable.

For instance, on March 5, 2024, PostHog recorded 26,585 for a specific event (button press later in the app), while Firebase had 26,712—only a very small difference which could also be because one of the dashboards takes my timezone into account and the other doesn't. Not sure, anyways, it works.

Yet, for the initial app open event "onboarding screen shown," there's a significant difference: On March 5, 2024, Firebase shows 174, but PostHog only 5 (!) events.

Function looks like this:

Future<void> logEvent({
    required String name,
    Map<String, dynamic>? parameters,
}) async {
    // Posthog().capture(...
    // FirebaseAnalytics.instance.logEvent(...

@marandaneto
Copy link
Member

@jakobhec can you reproduce this issue? can you provide a MRE? I cannot reproduce myself sadly, everything works as expected.

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

@marandaneto If the app is opened, 15 events are triggered by a user, and then the app is closed, will PostHog send those events?
Currently thinking about the MRE

@marandaneto
Copy link
Member

@marandaneto If the app is opened, 15 events are triggered by a user, and then the app is closed, will PostHog send those events? Currently thinking about the MRE

Yes, by default the SDK will only send after it's accumulated at least 20 events or the app is idle for at least 30 seconds.

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

@marandaneto just to clarify: in the example there were less than 20 events and the app was not idle for at least 30 secondes. Shouldn't that mean that nothing will be sent?

Or does posthog also trigger on app close?

@marandaneto
Copy link
Member

@marandaneto just to clarify: in the example there were less than 20 events and the app was not idle for at least 30 secondes. Shouldn't that mean that nothing will be sent?

Or does posthog also trigger on app close?

It's either at least 20 events or after 30 seconds the app is opened, not idle, sorry wrong wording.

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

@marandaneto thanks for clarifying.

So if a user opens an app for the first time, sees the onboarding flow, slides through the first 3 onboarding screens (triggering < 20 events in total) and then leaves the app after 15 seconds. Will Posthog send events?

@marandaneto
Copy link
Member

@marandaneto thanks for clarifying.

So if a user opens an app for the first time, sees the onboarding flow, slides through the first 3 onboarding screens (triggering < 20 events in total) and then leaves the app after 15 seconds. Will Posthog send events?

yes, after 30 seconds if the app is open (it can be in the background), but not closed (forcefully killed from recent apps), events should have been sent.

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

@marandaneto As far as I understand this makes it impossible to use Posthog for onboarding A/B testing and onboarding event tracking. Because if users don't like the onboarding in the first 15 seconds, then they most likely kill the app and delete it.

I would really like to use Posthog for this.

Can I override this behavior? Or manually send off events before the user forcefully closes the app? For example by using this: https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html.

@marandaneto marandaneto mentioned this issue Mar 7, 2024
4 tasks
@marandaneto
Copy link
Member

Usually, people don't kill the app, either they uninstall it or just leave it in the background (in this case is fine).
But you can call flush which forcefully sends all pending events, the flush is being added here #92

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

@marandaneto flush is great! But even if only 10% kill the app, it would make a big difference for a/b testing.

I think that might explain a small part of the difference between firebase analytics (174 events) and Posthog (5 events). But I would assume that 100-165 events are still missing. I'll test some more and keep you informed

@jakobhec
Copy link
Author

jakobhec commented Mar 7, 2024

I am testing it like this now:

class _MyAppState extends State<MyApp> {
  late final AppLifecycleListener _listener;

  @override
  void initState() {
    super.initState();
    _listener = AppLifecycleListener(
        onPause: () => Posthog().flush(),
    );

To be clear: I think that the main issue that leads to missing events after startup is not resolved.

@marandaneto
Copy link
Member

@jakobhec then I need an MRE, I cannot reproduce this.

@jakobhec
Copy link
Author

jakobhec commented Apr 2, 2024

If anyone else runs into this issue: delaying to capture initial events and manually calling flush() seems to work:

This is how I manually call flush():

// in the root StatefulWidget initState() method
_listener = AppLifecycleListener(
    onPause: () => Posthog().flush()
);

And I've created a function that delays the initial events while keeping correct timestamps:

final ts = DateTime.now().toIso8601String();

// I store a timestamp of the first app open in shared preferences.
// I use that to calculate the necessary delay to ensure that it is captures events at least 3 seconds after first app open.
// final msDelayToEnsureDelivery = ... 

Future.delayed(Duration(milliseconds: msDelayToEnsureDelivery)).then((_) {
  Posthog().capture(eventName: name, properties: {
    ...properties,
    '\$timestamp': ts,  // manually set the correct timestamp
  });
});

Would be very happy to hear alternate ideas :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants