Assessing Heatmaps
PostHogOfficialPublished by PostHog
- Skill
- Research and analysis
- Data and AI
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill enables an agent to interpret raw heatmap data—including clicks, rage clicks, and scroll depth—by cross-referencing it with autocapture events. Since the agent cannot visually see the page, it uses coordinate data and element identity to translate abstract interactions into actionable insights. It provides a structured approach to identifying broken UI elements, misplaced calls-to-action, and engagement drop-offs, ultimately offering concrete recommendations to improve page performance.
What it does
- Retrieves click, rage-click, and scroll-depth data for specific URLs.
- Identifies the identity of hot elements by matching coordinates with autocapture event data.
- Calculates the percentage of interactions occurring below the fold to optimize layout.
- Generates saved heatmaps in PostHog for visual verification by the user.
- Drills down into specific interaction clusters to investigate session replays.
- Produces a prioritized report of UI problems and evidence-based improvement recommendations.
When to use it
- When users ask why specific elements are not receiving clicks.
- To investigate areas of a page where users exhibit frustration via rage-clicks.
- To determine if important content or CTAs are positioned below the scroll fold.
- When auditing a page to improve conversion or user engagement.
- To validate whether users perceive non-interactive elements as clickable.
Advantages
- Translates raw coordinate data into meaningful element-based insights.
- Distinguishes between desktop and mobile behavior through viewport segmentation.
- Prioritizes findings based on signal strength, such as rage-click clusters.
- Provides a clear link between user behavior data and specific UI design changes.
Usage examples
- “Why are users not clicking the 'Sign Up' button on our pricing page?”
- The agent pulls click and scroll data, identifies if the button is below the fold, checks for rage-clicks, and suggests moving the CTA higher if data shows users are not reaching it.
- “Analyze the heatmap for our homepage and tell me what to change.”
- The agent identifies top-engaged elements, highlights dead zones, reports on scroll depth, and recommends specific layout adjustments based on the observed interaction patterns.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/posthog/assessing-heatmaps/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip assessing-heatmaps.zip -d .agents/skills
Documentation by PostHog
Assessing heatmaps
A heatmap answers "where do people interact with this page?" — clicks, rage clicks, mouse movement, and how
far down they scroll. The data is pure geometry: pointer_relative_x (0..1 across the viewport), pointer_y
(absolute pixels down the page), and a count per spot. It does not know what was clicked. Turning
"lots of clicks at (0.5, 220)" into "lots of clicks on the Pricing nav link" is the whole job, and it comes
from cross-referencing autocapture on the same URL.
Core principle: coordinates + meaning
You can't see the page — there is no screenshot in your context. A good assessment fuses two sources and leans on autocapture to supply the layout/identity you can't see:
Heatmap data — where interactions land and how far people scroll (
heatmaps-list).Autocapture — what element sits under the hot spots, by element text / selector on the same page. This is what turns coordinates into meaning; without it you only have dots.
When the user wants to see the heatmap, create a saved heatmap (Step 4) — that renders the page with the data overlaid for them to open in PostHog. You reason from the data; they look at the picture.
The flow
Step 1: Pin the page and window
You need an exact url_exact (one page) or a url_pattern (regex, to aggregate across query strings). Confirm
the URL with the user if ambiguous. Default to the last 7 days; widen to 30 if volume is low. Heatmap data is
retained for 90 days.
Step 2: Pull the data
Call heatmaps-list once per signal you care about (or query the heatmaps table directly via SQL — see the
querying-posthog-data skill, models-heatmaps):
type: "click"— the primary "what draws attention" map.type: "rageclick"— repeated frustrated clicks. The single strongest "something is broken or misleading" signal. Any meaningful rageclick cluster deserves a callout.type: "scrolldepth"— how far people get. Use it to find the fold and spot CTAs that sit below where most people ever scroll.
Use aggregation: "unique_visitors" when you care about how many people (not how many clicks); total_count
exaggerates a few heavy clickers.
Click results come back hottest-first and are capped at limit (default 500). A busy page can have
thousands of distinct coordinates, so the default page plus the fold summary is almost always enough — the
hottest points are what analysis turns on. Don't ask for everything: raise limit or page with offset only
when you specifically need more, and check has_more to know the list was truncated. scrolldepth ignores
limit and always returns every bucket.
Step 2b: Above the fold — read the fold summary
For the click types, heatmaps-list returns a fold object alongside results:
pct_below_fold— share of non-fixed interactions that landed below the user's initial viewport (they had to scroll to reach them). This is one of the highest-value findings: content people actively click that sits below the fold is a prime candidate to move up.below_fold_count/total_count— the raw counts behind the percentage (fixed-position elements are excluded, since they're always on screen).median_viewport_height— the typical fold line in CSS pixels, to recommend against.
Report it concretely, e.g. "the fold is ~600px for most visitors, yet 35% of clicks land below it, so users
scroll before interacting — that content is a candidate for the first screen." Segment by device with
viewport_width_min/viewport_width_max (desktop and mobile have very different folds) and read fold per
band rather than blending them.
Need a distribution rather than a single percentage (e.g. clicks bucketed by how far below the fold)? Drop to
SQL on the raw heatmaps table, which has y and viewport_height in the same scaled units — see the
querying-posthog-data skill, models-heatmaps.
Step 3: Name the hot elements (autocapture overlap)
For each notable cluster, find what's actually there. Query autocapture on the same URL — either via the
exploring-autocapture-events skill or directly:
SELECT properties.$el_text AS text, count() AS clicks
FROM events
WHERE event = '$autocapture'
AND properties.$current_url = 'https://example.com/pricing'
AND timestamp >= now() - INTERVAL 7 DAY
GROUP BY text
ORDER BY clicks DESC
LIMIT 25elements_chain gives the selector/DOM path when you need to disambiguate two elements with the same text.
Match autocapture's top elements to the heatmap's hot coordinates: clicks concentrated on something that is
not a link or button (plain text, an image, a disabled control) is a classic "users expect this to be
clickable" finding.
Step 4: Give the user a heatmap to look at (optional)
You can't see the page, but the user can. When a visual would help them follow your findings, create a saved heatmap so they can open the rendered page with the data overlaid in PostHog:
heatmaps-saved-createwith the pageurl(type defaults toscreenshot). This enqueues a headless render — it is asynchronous. Passwidthsmatching the viewport band you analyzed in Step 2.Poll
heatmaps-saved-get(by the returnedshort_id) untilstatusiscompleted, then tell the user it's ready to view in PostHog.
This is for the human's benefit — your own reasoning still comes from the Step 2 data and the Step 3 autocapture identity, not from the picture.
Step 5: Drill into hotspots (when you need the "why")
For a surprising cluster, heatmaps-events returns the individual sessions behind specific points. Hand the
session IDs to the investigating-replay skill to watch what people actually did.
Step 6: Summarize and recommend
Produce a short, concrete report:
What the heatmap shows — top engaged elements, dead zones, scroll reach, and the above/below-the-fold click split (e.g. "viewport is ~600px for most visitors, yet 35% of clicks land below it").
Problems, ranked by signal strength — rage-click clusters first, then clicks on non-interactive elements, then important CTAs sitting below the scroll cliff, then ignored primary actions.
Recommendations tied to evidence — move/raise a CTA above the fold, make a clicked-but-dead element a real link, cut competing elements near a rage-click cluster, etc. Every recommendation should cite the signal it came from.
Reading the signals
| Signal | Likely meaning | Typical recommendation |
|---|---|---|
| Rage clicks on an element | Broken, slow, or looks-clickable-but-isn't | Fix the handler, add feedback, or make it actually interactive |
| Many clicks on non-link text/image | Users expect it to be clickable | Make it a link/button, or remove the affordance |
| Primary CTA gets few clicks | Buried, low-contrast, or out-competed | Raise it, increase contrast, reduce nearby noise |
| Scroll cliff before key content | Content/CTA is below where people stop | Move it up or add a reason to scroll |
| High % of clicks below the fold | Engaged content sits below the initial viewport — users scroll before interacting | Move the most-clicked elements onto the first screen |
| Hot clicks on nav, cold body | Page isn't delivering; people bail to nav | Re-evaluate the page's core content |
Gotchas
Heatmaps must be opted in (
Team.heatmaps_opt_in). Ifheatmaps-listreturns nothing for a page that clearly gets traffic, capture may be off or the URL is wrong — check both before concluding "no engagement".Coordinates are scaled by a factor of 16 in storage; the API already returns CSS-pixel
pointer_yand relative x, so use the API/tool values directly rather than the raw table columns.You can't see the screenshot. The saved-heatmap render is for the user to open in PostHog; don't claim to have looked at the page. Ground every layout claim in autocapture identity + coordinates, not vision.
Saved-heatmap rendering is async. After
heatmaps-saved-create, pollheatmaps-saved-getuntilstatusiscompletedbefore telling the user it's viewable. Onlyscreenshot-type heatmaps render an image;iframeandrecordingtypes do not.Mind the viewport. A desktop click map and a mobile one are different pages' worth of behavior — filter with
viewport_width_min/viewport_width_maxrather than blending them.
Files
- ATTRIBUTION.mdAdded by AutoGineer855 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md9.7 KiB
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- PostHog
- Publisher
- PostHog (Official)
- Source
- PostHog/skills · skills/omnibus/assessing-heatmaps · commit a5d30e7
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by PostHog.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download assessing-heatmaps.zip