-
Notifications
You must be signed in to change notification settings - Fork 39
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
Heatmap support #68
Comments
I love Posthog and this feature would be such a gamechanger. Can you share more details on your ideas for the implementation? I'd love to contribute. |
To capture events manually, you have to capture an event called ElevatedButton(
onPressed: () {
Posthog()
.capture(eventName: '\$autocapture', properties: {
'\$event_type': 'touch',
'\$touch_x': 100, // read the position
'\$touch_y': 100, // read the position
});
},
child: const Text("Capture touch event"),
), The goal would be to do that automatically instead of calling The problem is that heatmaps is only available via the toolbar (Web only), so you'd not be able to see the heatmaps for Mobile yet anyway, this would be a feature request, Heatmaps for Mobile in general. The suggested approach would be useful anyway since more events would be captured automatically instead of manually. We can achieve that by doing something similar to https://github.com/ueman/sentry-dart-tools/blob/main/sentry_flutter_plus/lib/src/widgets/click_tracker.dart which is a widget wrapper that then can "intercept" every click. |
The proposed approach seems to be rather complicated given a mobile toolbar would be required to have. Though maybe I am missing something, but wouldn't it be possible if for web where clicks are automatically tracked, but the scroll position is incorrect. We would override the scroll manager and provide it with the correct scroll position from Flutter? |
Here is a quick proof of concept for this ☺ It's not ideal, e.g. if some areas like a nav bar are not scrollable. child: NotificationListener(
onNotification: (notification) {
if (notification is ScrollMetricsNotification) {
if (notification.metrics.axis == Axis.vertical) {
updateScrollData(createJSInteropWrapper(ScrollContext(
// todo: Verify which numbers to put here exactly.
maxScrollHeight: notification.metrics.maxScrollExtent,
maxScrollY: notification.metrics.maxScrollExtent,
lastScrollY: notification.metrics.pixels,
maxContentHeight: notification.metrics.maxScrollExtent +
notification.metrics.viewportDimension,
maxContentY: notification.metrics.maxScrollExtent +
notification.metrics.viewportDimension,
lastContentY: notification.metrics.pixels +
notification.metrics.viewportDimension,
)));
}
}
return false;
}, @JSExport()
class ScrollContext {
ScrollContext({
this.maxScrollHeight,
this.maxScrollY,
this.lastScrollY,
this.maxContentHeight,
this.maxContentY,
this.lastContentY,
});
double? maxScrollHeight;
double? maxScrollY;
double? lastScrollY;
double? maxContentHeight;
double? maxContentY;
double? lastContentY;
} import 'dart:js_interop';
import 'package:simpleclub_flutter/core.dart';
@JS()
external void updateScrollData(JSObject newContext); <script>
// export interface ScrollContext {
// // scroll is how far down the page the user has scrolled,
// // content is how far down the page the user can view content
// // (e.g. if the page is 1000 tall, but the user's screen is only 500 tall,
// // and they don't scroll at all, then scroll is 0 and content is 500)
// maxScrollHeight?: number
// maxScrollY?: number
// lastScrollY?: number
// maxContentHeight?: number
// maxContentY?: number
// lastContentY?: number
// }
// This class is responsible for tracking scroll events and maintaining the scroll context
class ScrollManagerFlutter {
constructor(instance) {
this.instance = instance;
}
getContext() {
return this.context
}
resetContext() {
const ctx = this.context
// update the scroll properties for the new page, but wait until the next tick
// of the event loop
// setTimeout(this.updateScrollData, 0)
return ctx
}
updateScrollData = (newContext) => {
this.context = newContext;
}
startMeasuringScrollPosition() {}
scrollElement() {
return window.document.querySelector('flutter-view');
}
scrollY() {
return this.context.lastScrollY;
}
scrollX() {
return this.context.lastScrollX;
}
}
</script> posthog.init('phc_VXXWtJlclxOXCSN3qGxCye5jGNEJIlMiy0ZK39pi4Hy', {
api_host:'https://l.simpleclub.com',
person_profiles: 'identified_only' // or 'always' to create profiles for anonymous users as well
});
setTimeout(() => {
const scrollManagerFlutter = new ScrollManagerFlutter(posthog);
posthog.scrollManager = scrollManagerFlutter;
console.log('scrollManagerFlutter', scrollManagerFlutter);
}, 1000);
function updateScrollData(newContext) {
posthog.scrollManager.updateScrollData(newContext);
} |
@IchordeDionysos this is Flutter web only right? |
@marandaneto yes, given the way that Heatmaps are displayed and the need to build some mobile toolbar 🤔 The long term solution might work differently. |
Description
https://posthog.com/docs/toolbar/heatmaps
We'd need to create a Widget wrapper that tracks and captures every interaction such as clicks, etc.
You can manually do this though, by capturing events manually.
The text was updated successfully, but these errors were encountered: