{"id":371538,"date":"2026-09-27T16:12:47","date_gmt":"2026-09-27T16:12:47","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/sc-heatmap\/"},"modified":"2026-09-27T18:15:33","modified_gmt":"2026-09-27T18:15:33","slug":"incode-heatmap","status":"publish","type":"plugin","link":"https:\/\/tir.wordpress.org\/plugins\/incode-heatmap\/","author":23087910,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.6.5","stable_tag":"0.6.5","tested":"7.1.2","requires":"5.8","requires_php":"7.4","requires_plugins":null,"header_name":"Incode Heatmap","header_author":"Adri\u00e1n Alcal\u00e1","header_description":"Self-hosted heatmaps (clicks, movement, scroll). No third-party services, privacy-first. Lightweight: the visitor never pays the render cost.","assets_banners_color":"716c89","last_updated":"2026-09-27 18:15:33","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/adrianalcala.es\/plugins-wordpress\/","header_author_uri":"https:\/\/adrianalcala.es\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":68,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.6.4":{"tag":"0.6.4","author":"adrianincode","date":"2026-09-27 16:12:35","revision":3715709},"0.6.5":{"tag":"0.6.5","author":"adrianincode","date":"2026-09-27 18:15:33","revision":3715949}},"upgrade_notice":{"0.6.0":"<p>Scroll history is now kept per day so retention prunes it properly. The database\nupdate runs on its own the first time you load the dashboard.<\/p>","0.5.0":"<p>Adds a setup wizard and an in-plugin quick guide, and reorganises the admin screens.\nRecommended for all users.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3715719,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3715719,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3715719,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3715719,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.6.4","0.6.5"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3715737,"resolution":"1","location":"assets","locale":"","width":1440,"height":900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3715737,"resolution":"2","location":"assets","locale":"","width":1440,"height":900},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3715737,"resolution":"3","location":"assets","locale":"","width":1440,"height":900},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3715737,"resolution":"4","location":"assets","locale":"","width":1440,"height":900},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3715737,"resolution":"5","location":"assets","locale":"","width":1440,"height":900}},"screenshots":{"1":"Click heat map overlaid on the live page.","2":"Scroll-depth map.","3":"Confetti view coloured by click timing.","4":"The Maps screen, with every page that has data.","5":"Settings screen."}},"plugin_section":[],"plugin_tags":[232,5375,984,6207,45277],"plugin_category":[36,55],"plugin_contributors":[278539],"plugin_business_model":[],"class_list":["post-371538","plugin","type-plugin","status-publish","hentry","plugin_tags-analytics","plugin_tags-click-tracking","plugin_tags-conversion","plugin_tags-heatmap","plugin_tags-scrollmap","plugin_category-analytics","plugin_category-seo-and-marketing","plugin_contributors-adrianincode","plugin_committers-adrianincode"],"banners":{"banner":"https:\/\/ps.w.org\/incode-heatmap\/assets\/banner-772x250.png?rev=3715719","banner_2x":"https:\/\/ps.w.org\/incode-heatmap\/assets\/banner-1544x500.png?rev=3715719","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/incode-heatmap\/assets\/icon-128x128.png?rev=3715719","icon_2x":"https:\/\/ps.w.org\/incode-heatmap\/assets\/icon-256x256.png?rev=3715719","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/incode-heatmap\/assets\/screenshot-1.png?rev=3715737","caption":"Click heat map overlaid on the live page."},{"src":"https:\/\/ps.w.org\/incode-heatmap\/assets\/screenshot-2.png?rev=3715737","caption":"Scroll-depth map."},{"src":"https:\/\/ps.w.org\/incode-heatmap\/assets\/screenshot-3.png?rev=3715737","caption":"Confetti view coloured by click timing."},{"src":"https:\/\/ps.w.org\/incode-heatmap\/assets\/screenshot-4.png?rev=3715737","caption":"The Maps screen, with every page that has data."},{"src":"https:\/\/ps.w.org\/incode-heatmap\/assets\/screenshot-5.png?rev=3715737","caption":"Settings screen."}],"raw_content":"<!--section=description-->\n<p>Incode Heatmap shows you how visitors really use your pages \u2014 where they click, where they\nhesitate and how far down they read \u2014 and keeps every measurement in your own WordPress\ndatabase. No account, no external service, no data leaving your server.<\/p>\n\n<p>The heavy work happens in the administrator's browser, on demand: aggregating points and\npainting the map. On the front-end there is only a small, deferred, consent-aware tracker,\nso real visitors pay virtually nothing for it.<\/p>\n\n<p><strong>What you get<\/strong><\/p>\n\n<ul>\n<li>Click heat map and mouse-movement heat map.<\/li>\n<li>Scroll-depth map: see the line where readers drop off.<\/li>\n<li>\"Confetti\" view: every click coloured by the moment it happened.<\/li>\n<li>Device segmentation (desktop \/ tablet \/ mobile) \u2014 separate maps, because they rarely agree.<\/li>\n<li>Configurable sampling, so the database does not balloon on a busy site.<\/li>\n<li>Consent aware: Complianz, Cookiebot and Google Consent Mode v2 are detected automatically,\nplus Do-Not-Track.<\/li>\n<li>Input masking: nothing typed into a form is stored.<\/li>\n<li>Front-end viewer: the heat is painted over your live page, in its real context \u2014 not on\na screenshot inside the dashboard.<\/li>\n<li>Automatic retention with a daily cleanup job.<\/li>\n<li>A setup wizard and an in-plugin quick guide, so the first map takes a couple of minutes.<\/li>\n<\/ul>\n\n<p><strong>No limits<\/strong><\/p>\n\n<p>Everything above is in this plugin, free and without limits: no caps on pages, on\nevents, or on how long you keep them. Nothing is locked, metered or timed out.<\/p>\n\n<p><strong>How it works<\/strong><\/p>\n\n<p>The tracker batches events and sends them with <code>navigator.sendBeacon<\/code> to a REST endpoint on\nyour own site. Coordinates are stored resolution-independently, so a map recorded on a 4K\nmonitor lines up with one recorded on a laptop. Nothing is computed on the visitor's page\nbeyond collecting the events; rendering happens only when an administrator opens a map.<\/p>\n\n<h3>Privacy<\/h3>\n\n<p>Incode Heatmap stores behavioural data (clicks, mouse movement and scroll depth) on your own\nserver only. It does not collect names, email addresses or IP addresses, and text typed\ninto form fields is masked. Capture runs only after consent when a consent banner is\npresent, and honours the browser Do Not Track signal. Data is deleted automatically after\nthe retention period you configure. The plugin registers suggested privacy-policy text and\nintegrates with WordPress' personal-data export and erase tools.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>incode-heatmap<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install the ZIP from\nPlugins \u2192 Add New \u2192 Upload Plugin.<\/li>\n<li>Activate it. The setup wizard asks three questions and leaves the plugin measuring.<\/li>\n<li>Open any page of your site as an administrator and use the \"Heatmap\" button in the\nadmin bar to see the map over that page.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20send%20my%20visitors%27%20data%20to%20a%20third%20party%3F\"><h3>Does this send my visitors' data to a third party?<\/h3><\/dt>\n<dd><p>No. Everything is stored in your WordPress database and never leaves your server.<\/p><\/dd>\n<dt id=\"will%20it%20slow%20down%20my%20site%3F\"><h3>Will it slow down my site?<\/h3><\/dt>\n<dd><p>The front-end tracker is a few KB, loads deferred after everything else and sends batched\nevents. All aggregation and rendering happens in the administrator's browser, on demand,\nso regular visitors do not pay for it.<\/p><\/dd>\n<dt id=\"is%20it%20gdpr%20compliant%3F\"><h3>Is it GDPR compliant?<\/h3><\/dt>\n<dd><p>It is built to respect consent: it can require analytics consent (Complianz, Cookiebot,\nConsent Mode v2), honours Do-Not-Track, masks form input, stores no personal identifiers\nand deletes data after a retention period you choose. Compliance also depends on how you\nconfigure and disclose it on your own site.<\/p><\/dd>\n<dt id=\"i%20browse%20my%20site%20and%20no%20data%20shows%20up.\"><h3>I browse my site and no data shows up.<\/h3><\/dt>\n<dd><p>Administrators and editors are excluded on purpose, so your own browsing does not pollute\nthe data. Open the page in a private window to test it.<\/p><\/dd>\n<dt id=\"how%20do%20i%20exclude%20certain%20pages%20or%20roles%3F\"><h3>How do I exclude certain pages or roles?<\/h3><\/dt>\n<dd><p>Excluded roles (administrators and editors by default) are never tracked, and you can list\nURL patterns to include or exclude from the settings screen.<\/p><\/dd>\n<dt id=\"how%20long%20is%20the%20data%20kept%3F\"><h3>How long is the data kept?<\/h3><\/dt>\n<dd><p>As many days as you set under Retention (60 by default). A daily task deletes anything\nolder on its own.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.6.5<\/h4>\n\n<ul>\n<li>Fixed: if a second copy of the plugin code is active at the same time, it now stays idle instead of stopping the site with a fatal error.<\/li>\n<\/ul>\n\n<h4>0.6.4<\/h4>\n\n<ul>\n<li>Renamed to Incode Heatmap for the WordPress.org directory.<\/li>\n<\/ul>\n\n<h4>0.6.3<\/h4>\n\n<ul>\n<li>Housekeeping only: no user-visible changes in this edition.<\/li>\n<\/ul>\n\n<h4>0.6.2<\/h4>\n\n<ul>\n<li>Admin notices shown on the plugin screens are readable again: they were\ninheriting the white text of the header and came out white on white.<\/li>\n<li>The \"Privacy decided\" line of the setup checklist now describes the privacy\nsettings you actually have. It used to claim consent was required and\nDo-Not-Track honoured even when both were switched off.<\/li>\n<\/ul>\n\n<h4>0.6.1<\/h4>\n\n<ul>\n<li>A missing plugin file no longer takes the whole site down: the modules are\nchecked before they are loaded, and if any is missing the plugin stays inert\nand says so in the dashboard instead of throwing a fatal error.<\/li>\n<\/ul>\n\n<h4>0.6.0<\/h4>\n\n<ul>\n<li>Scroll history is now stored per day, so retention prunes it like everything\nelse instead of keeping one ever-growing row per page.<\/li>\n<li>Internal: schema version 3, applied automatically on update.<\/li>\n<\/ul>\n\n<h4>0.5.0<\/h4>\n\n<ul>\n<li>New: setup wizard on activation \u2014 three questions and the plugin is measuring.<\/li>\n<li>New: in-plugin quick guide with the four steps, how to read a map and the frequent\nquestions.<\/li>\n<li>Reorganised admin: shared header with live status, cards instead of one long form, and\nkey figures on the Maps screen.<\/li>\n<li>Settings now expose everything that previously required editing code: page whitelist,\nextra masking selectors and data purge on uninstall.<\/li>\n<li>Removed an unused admin script that was still being loaded.<\/li>\n<\/ul>\n\n<h4>0.4.1<\/h4>\n\n<ul>\n<li>Sampling and retention fixes; smaller footprint on busy sites.<\/li>\n<\/ul>\n\n<h4>0.4.0<\/h4>\n\n<ul>\n<li>Front-end viewer: fixed a REST nonce issue that could return 403 on the front-end.<\/li>\n<li>Confetti view coloured by click timing.<\/li>\n<li>GDPR: suggested privacy-policy content and personal-data exporter\/eraser hooks.<\/li>\n<li>Server-side revalidation of role and URL rules on ingestion (defence in depth).<\/li>\n<li>Performance: the page list for the viewer is loaded on demand.<\/li>\n<li>Internationalisation: all user-facing strings are translatable (text domain <code>incode-heatmap<\/code>).<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Initial release: click and scroll capture, batched REST ingestion, admin-side\naggregation and the click heat map viewer. Consent and retention from day one.<\/li>\n<\/ul>","raw_excerpt":"Self-hosted heat maps: clicks, mouse movement and scroll depth, stored in your own database. Privacy-first, no third-party services.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/371538","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=371538"}],"author":[{"embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/adrianincode"}],"wp:attachment":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=371538"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=371538"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=371538"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=371538"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=371538"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=371538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}