# Martez > Martez connects Matomo Analytics with Meta and Google Ads to gain insights into marketing KPIs like CPC, ROAS, CLV and more. It is currently in private beta. The team also builds Matomo Heatmap Helper, a free, open-source browser extension that fixes common Matomo heatmap screenshot issues. Every blog post is also available as plain markdown by appending `.md` to its URL. The full content of all posts is at /llms-full.txt. ## Product - [Martez](https://martez.io/): Marketing intelligence for Matomo Analytics — connects Matomo with Meta and Google Ads. - [Matomo Heatmap Helper](https://martez.io/opensource/matomo-heatmap-helper): A free, open-source browser extension to capture identical Matomo heatmap screenshots. ## Blog - [Why Matomo's log importer fails: invalid log lines, JSON errors, and silent piped logging](https://martez.io/blog/matomo-import-logs-not-working.md): Matomo's import_logs.py rarely tells you what's actually wrong. A JSONDecodeError almost always means --url is pointing at the wrong place, every line counted as an 'invalid log line' means your log format doesn't match, and a piped import that records nothing is usually just buffering. Here's how to read each failure and fix it on Matomo 5.x. - [Matomo ecommerce not tracking? Why your orders and products reports stay empty](https://martez.io/blog/matomo-ecommerce-not-tracking.md): Matomo Ecommerce is two separate things wearing one name: a setting that makes the reports exist, and tracking calls that fill them. Most stores only have the first. Here's why your Orders and Products reports read zero, and how to wire up the half that's actually missing. - [Matomo, multiple sites, and the data that keeps landing under one site](https://martez.io/blog/matomo-multiple-sites-domains-measurables.md): If every site reports into the same Matomo, or a second tracking snippet kills the first, or you're hunting for a per-site token_auth that doesn't exist, you're tangling three things Matomo keeps strictly separate: measurables, domains, and tokens. Here's the model that fixes all of it. - [Does Matomo need a consent banner? Cookieless tracking, fingerprinting, and making 'Refuse' actually work](https://martez.io/blog/matomo-consent-cookieless-tracking.md): Matomo's cookieless config_id isn't a classic fingerprint, ePrivacy and GDPR are two separate questions, and the reason 'Refuse' doesn't stop your tracking is almost always a double-injected tracker. Here's the config behind all three. Not legal advice, just the mechanics. - [Why your Matomo reports are suddenly full of bot traffic (and how to get it out)](https://martez.io/blog/exclude-bots-from-matomo.md): If your Matomo visits doubled overnight, your server-side tracker reports two to three times what the JavaScript tag does, or you're drowning in Direct Entry, one-page, zero-second hits, bots are almost certainly the cause. Matomo already filters the honest ones. Here's how to handle the rest and clean up the reports you already have. - [Where Matomo's country flags come from (and how to change them)](https://martez.io/blog/matomo-country-flags-geolocation.md): The little flag next to each visitor in Matomo isn't guessed from language or timezone; it's the country your geolocation database resolved from the visitor's IP. So a wrong flag is almost always a geolocation problem, not a flag problem. Here's how country detection actually works, why one looks wrong, and how to swap the icons. - [Your Matomo map shows every visitor as 'Unknown'? Set up GeoIP2 with the free GeoLite2 database](https://martez.io/blog/matomo-geoip2-geolite2-setup.md): If your self-hosted Matomo resolves visitors to 'Unknown' or one default country, you're almost always missing a GeoIP2 database. The old .dat downloads are dead and GeoLite2 now needs a free license key. Here's the current Matomo 5.x setup, why it broke, and how to keep it updating itself. - [Matomo archiving is eating your CPU and RAM: fixing 'Allowed memory size exhausted' and scaling on-premise](https://martez.io/blog/matomo-archiving-memory-cpu-scaling.md): core:archive dies on month and year with a DataTable.php fatal, MySQL CPU pins for no reason, and raising memory_limit never helps. It's almost always one thing: archiving, not tracking, is what makes Matomo heavy. Here's why more RAM doesn't fix it and what to tune instead. - [Why your Matomo Campaigns report is empty (and why the URL says gad_source=1)](https://martez.io/blog/matomo-campaign-tracking-utm-gad-source.md): Two campaign-tracking symptoms come up constantly in Matomo 5.x: the Campaigns report stays empty even though tagged links get visits, and the visit log shows ?gad_source=1 instead of your UTM parameters. Neither is usually a bug. Here's the mechanism behind each and exactly how we fix them. - [Fix Matomo database errors: access denied, connection refused, and missing privileges](https://martez.io/blog/fix-matomo-database-errors.md): Matomo's database errors look cryptic, but the SQLSTATE code in the message tells you exactly which half of the problem you're in. Here's how to read [1045], [2002], and the missing-privilege warnings, and the specific fix for each in Matomo 5.x. - [How Matomo counts visitors: unique visitors, visits, and unique pageviews explained](https://martez.io/blog/matomo-unique-visitors-vs-visits.md): Matomo's visitor numbers stop being mysterious once you know how it decides who is who and when it starts counting again. Here's the recognition model underneath unique visitors, visits, and unique pageviews in Matomo 5, plus why daily uniques don't sum and how server-side tracking splits one person into many. - [Tracking Matomo from your server: the HTTP Tracking API and token_auth](https://martez.io/blog/matomo-http-tracking-api-server-side.md): The event happened on your server, not in a browser, so the JavaScript snippet never saw it. Here's how to record it with Matomo's HTTP Tracking API: the parameters that actually matter, when you need token_auth, and whether you can stop strangers spamming the public matomo.php endpoint. - [Why your self-hosted Matomo returns a 502 the moment it sits behind a reverse proxy](https://martez.io/blog/self-host-matomo-reverse-proxy-502.md): Matomo loads fine on its direct port, then throws a 502 Bad Gateway the second Caddy or Nginx is in front of it. The proxy log says 'connection refused', and that one word tells you exactly what's wrong: your proxy is dialing the host-published port from inside the Docker network, where it doesn't exist. Here's the fix, plus how to size the box Matomo runs on. - [Matomo cron archiving fails with "Got invalid response from API request" (or "Processed 0 archives")](https://martez.io/blog/matomo-cron-archiving-invalid-response.md): Your scheduled core:archive job either errors out with 'the response was empty' or runs clean, prints 'Processed 0 archives,' and leaves dashboards frozen on yesterday's numbers. The two symptoms have different causes. Here's how we diagnose and fix both on Matomo 5. - [Matomo says to set up a crontab for core:archive. Here's how to do it right](https://martez.io/blog/set-up-matomo-cron-archiving.md): Matomo's System Check tells you to run core:archive on a schedule, and your dashboards have started to crawl. Both are the same thing: browser-triggered archiving doesn't scale. Here's how to turn it off and run the archiver on cron correctly on Matomo 5. - ["Table log_bot_request doesn't exist - in plugin BotTracking": fixing Matomo archiving after an upgrade](https://martez.io/blog/matomo-bottracking-table-doesnt-exist.md): After upgrading to Matomo 5.6–5.8 (or installing through Softaculous), archiving dies with "Table '…_log_bot_request' doesn't exist - in plugin BotTracking". The BotTracking plugin's table never got created. Here's why, and how to put it back so the error doesn't come straight back. - [What Matomo's new AI Assistants and AI Chatbot reports actually mean (and how to hide the column)](https://martez.io/blog/matomo-ai-chatbot-reports.md): Matomo 5.8 added an 'AI Chatbot Requests' column to the All Websites dashboard plus a set of AI Assistants reports, and the names all sound the same. Here's what each of the three reports measures, why the chatbot numbers look so small, and how to get that column off your dashboard without switching tracking off. - [How to set up Matomo Heatmaps so the screenshot matches the page](https://martez.io/blog/how-to-set-up-matomo-heatmaps.md): Setup is two jobs, not one. Turning the plugin on takes ten minutes. Making the screenshot Matomo produces actually look like your live site is the longer half. Here's the path we walk through on every client setup. - [How we pick between Matomo Heatmaps, Hotjar, and Microsoft Clarity](https://martez.io/blog/matomo-heatmaps-vs-hotjar-vs-microsoft-clarity.md): Three tools that look similar in screenshots but solve different problems. Here's how we pick between them on client work, and what each is honestly good at. - [Why every Matomo paid-media review ends in a spreadsheet](https://martez.io/blog/tracking-ad-campaign-roi-in-matomo.md): Matomo tracks campaigns and runs multi-touch attribution, but it doesn't know what your ads cost. That one missing input is why every paid-media review ends in a spreadsheet. - [Why videos aren't loading in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-videos-not-loading.md): Matomo heatmap screenshots show black rectangles where your hero video, autoplay product reel, or background loop should be. The clicks are fine. Here's why the video doesn't paint and how we deal with it. - [Why tooltips and dropdowns are misaligned in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-tooltips-misaligned.md): Matomo heatmap screenshots can show tooltips, dropdowns, and badges floating at the top-left of the page when their containers don't have a positioning context. The clicks land where you'd expect; the overlays drift. Here's why it happens and how we deal with it. - [Why your sticky header repeats (or freezes) in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-sticky-header-repeating.md): Fixed and sticky headers either repeat down the page or freeze across the middle of Matomo heatmap screenshots, because Matomo renders the captured DOM as one tall image with no consistent viewport for them to anchor to. Here's why it happens and how we deal with it. - [Why relative URLs aren't loading in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-relative-urls-not-loading.md): Matomo heatmap screenshots break when your page uses relative paths. The renderer resolves them against Matomo's host instead of yours, so images, stylesheets, and fonts 404. Here's why it happens and how we deal with it. - [Why images aren't loading in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-images-not-loading.md): Matomo heatmap screenshots show broken-image placeholders when the image URLs in the captured snapshot won't resolve at view time: expired signed URLs, hot-link protection, or a CDN that blocks the request. The click data is fine. Here's why it happens and how we deal with it. - [Why iframes show up collapsed in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-iframes-collapsed.md): Cal.com, Calendly, YouTube, and HubSpot embeds capture as tiny default-height frames in Matomo heatmaps, often with an internal scrollbar. The clicks pile up on empty space and any insight into what visitors did inside the embed is lost. Here's why it happens and how we deal with it. - [Why fonts aren't loading in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-fonts-not-loading.md): Matomo heatmap screenshots fall back to Times New Roman or Arial when your @font-face files get blocked by CORS, locked to a hosted-font provider, or loaded after the snapshot is taken. Here's why it happens and how we deal with it. - [Why your Matomo heatmap cuts off past a certain point (and how to fix it)](https://martez.io/blog/matomo-heatmap-cut-off.md): Matomo heatmap screenshots go black or blank below a certain line when a sidebar, tabbed panel, or any container with a capped height clips its overflow during capture. The clicks are still recorded, just landing on empty space. Here's why it happens and how we deal with it. - [Why parts of your page are cut off in your Matomo heatmap (and how to fix it)](https://martez.io/blog/matomo-heatmap-content-cut-off.md): Matomo heatmap screenshots silently clip everything inside scroll containers and overflow:hidden wrappers. Sidebars, modals, and 'scrollytelling' layouts disappear past their visible edge, and clicks land on whatever was on screen at capture time. Here's why it happens and how we deal with it. - [How we deal with broken Matomo heatmap screenshots](https://martez.io/blog/introducing-matomo-heatmap-helper.md): Heatmap screenshots break on most modern sites because of how Matomo serializes and re-renders the DOM. Here are the patterns we kept running into, and a small open source extension we built to handle them. - [Why we're building marketing tools for Matomo](https://martez.io/blog/why-were-building-marketing-tools-for-matomo.md): Matomo is the right foundation for privacy-first web analytics. The bridges to the rest of the marketing stack mostly aren't there. That gap is what we're building into. - [Why your Matomo heatmap screenshots are broken (and how to fix them)](https://martez.io/blog/fix-broken-matomo-heatmap-screenshots.md): Matomo heatmap screenshots break because the page is saved as a DOM snapshot, then reconstructed later with CSS, fonts, images, and layout still coming from your site. Here's what causes each issue and how to fix it.