MarketUnlock Analytics

Sign in to your dashboard

Open your authenticator app and enter the 6-digit code.

ActionNeuro LLC · MarketUnlock

MarketUnlock Analytics
Landlord
Analytics
Monetization
Operations

Dashboard

Sites

listing status, tenant, routing, calls in this range. Pause routing when a tenant is on vacation or behind on rent.

Clients

who rents what, whether they are paid up, and how many leads each site sent them. Click a row to open the client.

New client

Rent roll

monthly rent minus Twilio number cost. Mark paid through when the tenant pays. Not Stripe billing — just the ledger you look at.

Phone numbers

Every Twilio number on this account, which site it rings, and who it forwards to. Rent first, then assign. Unassign keeps the number (Twilio still bills). Release deletes it.

Rent a number
Twilio webhook URLs

        

Site setup

Listing is yours. Tenant tab is what they will log in to change. Numbers stay under Landlord → Numbers.

Unique visitors

per day for the selected range
⬇ Content CSV

Today's forecast

projected end-of-day totals from the last 7 days' hourly curve

Sites

SiteVisitors

Top Sources

SourceVisitors

Top Pages

PageVisitors

Devices

DeviceVisitors

Widget Placements

PlacementRevenue
Visitors (30 min) —
Pageviews (30 min) —
last 30 min
PageVisitors

Sources

last 30 min
SourceVisitors

Devices

last 30 min
DeviceVisitors

Widget clicks

last 30 min — these are the money moments

three different populations, do not add them up · AI-referred = a person arrived from ChatGPT / Perplexity / Copilot / Gemini (channel "AI Assistants") · agent-capable = the visitor's browser exposes an in-page agent API (Edge Copilot Mode) — capable, not necessarily active, so an upper bound · tool calls = a page-declared WebMCP tool was actually invoked — the real activity signal, zero until the sites ship tools

Do agent sessions still see the widget?

the WEBMCP.md gate · if agent-capable sessions view or click the widget less than everyone else, on-page agent tools are costing revenue · leads born in agent-capable sessions carry the --muag placement marker — agents must never submit the Esy form, so a rising count is a warning, not a win

AI assistants sending people

referrer-based · humans, not bots

Agent-capable browsers

where navigator.modelContext exists

WebMCP tool calls

each tool a page declared and an agent invoked · fired via muaAgent()

By site

a site on a tracker older than 2026-09-06 cannot report agent-capable visits

Pages agents reach

pageviews by agent-capable and AI-referred visitors

Monetization Funnel

where visitors drop out between landing and earning

Traffic, no widget seen

widget missing or below the fold
PageViews

Seen, never clicked

weak placement or listings
PageImpressions

Clicked, no revenue yet

leads not converting on Esy's side
PageClicks

Movers vs previous period

Gainers

Losers

Page decay

second half of the selected range vs the first half — money pages quietly sliding

Revenue decaying

Traffic decaying

Engaged vs. Earns

each bubble is a page (size = visitors). Top-left = deeply read but under-monetized — your best widget-placement opportunities.

Content Performance

every page's traffic, engagement, and revenue side by side — click a column to sort. RPM = revenue per 1,000 pageviews.

Web Vitals

real-visitor page speed (p75, Google's threshold percentile). LCP = load, CLS = layout shift, INP = responsiveness. Green meets Google's "good" bar; red is "poor" and can cost rankings.

Inside this silo

each row is the next level down — click a folder to drill in · Δ compares the previous period of the same length · new = first pageview ever landed inside the selected range · search clicks/impressions come from Search Console when imported · click a column to sort

Esy widget coverage

each sub-silo with the Esy widget ids its pages show · dedicated = a widget that lives mostly on this silo · shared only = just the generic widget every silo gets · no widget = traffic but no impressions · sorted by visitors, so the top gaps are the ones worth a program-specific widget

Content cohorts

pages grouped by the month they first got a pageview, followed month by month since — is this month's new content earning like last month's did at the same age? · cells are per page so cohorts of different sizes compare · the oldest cohort holds every page that predates tracking

Improve — striking-distance queries

search queries ranked 4–20 on pages that already earn revenue. These are the cheapest wins: better internal links, refreshed content, or a dedicated page pushes them to page one.

Write — under-built high-RPM trades

trades that earn far more per pageview than the portfolio average but have thin content. Headroom = monthly $ if traffic grew to the portfolio's 75th percentile at current RPM.

Refresh — decaying earners

pages whose revenue or traffic dropped sharply between the first and second half of the period. Rescue these before rankings follow the trend.

Geo & Trades Performance

Rolled up from page URL slugs across every site — pageviews, widget CTR, conversions, revenue, and RPM per dimension. Click a column header to sort.

⬇ Export CSV

Search Performance

Search clicks & impressions joined to revenue by landing page. Revenue / query distributes each page's conversion revenue across the queries that drove its clicks — which search terms actually feed the money pages. Import data in Settings → Data & Integrations.

No search data yet — import it in Settings → Data & Integrations.

A/B Experiments

Whole run per test, not the date range. Start one with data-experiments="name:2" on the tracker tag.
No experiments running. Add data-experiments to the tracker tag to start one.

Tracking Health

Per-site last-seen pageview, tracker version, and 24h volume. A site going silent during active hours is the earliest sign of a broken tracker (the worst kind of outage — silent data loss).

Alerts

Conversion data freshness

Backups & delivery

⬇ Download backup (.ndjson.gz)

Esy Widget Performance

impression → view → click funnel from the tracker · conversions & revenue from your CSVs, joined by unique placement IDs

Click economics by widget type

listing (request-info) vs search (find-schools) — which widget kind earns the clicks

School economics

clicks on each school's widget card · conversions counted only after click tracking began, so $ / click compares like with like

Widget ranking

the live card order the sites fetch from /widget-ranking · auto-ranked by all-time $ / lead · type a slot number to pin a school there no matter what the maths say, ✕ to let it float again · sites pick up changes within ~25 min

Payout changes

schools whose $ / lead over the last 30 days moved 25%+ against the 90 days before — Esy changes payouts without notice, and this is where it shows · also fires the payout_change alert

Payout per lead by month

each school's average payout per lead, month by month (lead count underneath) · top schools by revenue

What gets clicked

which card element earns the click — school name vs logo vs button vs program link

YouTube

By day

YouTube revises recent days · AdSense revenue finalizes ~2 days later

Top videos

last import window

Amazon Associates

Clicks are first-party. Earnings come from an Associates Central Orders/Earnings CSV.

By

Recent orders

from the last uploaded Associates report · ship date, not click date

Form leads

Export CSV

Form snippet

Paste into a Hugo template. Keep the consent checkbox wording; the script stores the exact words shown.

Consent record

Calls by

Recent calls

newest first · page from the tel/sms tap just before the ring · tag booked/spam and block junk callers

Blocked callers

hangs up immediately on the next inbound. Leave site blank to block across every site.
⬇ Export

Scrubbed leads

who rejects leads, and which pages send them

Most recent scrubs

Revenue Attribution

Pacing

month-to-date vs the same day last month, then the year on the current pace

This month

Year

Time to convert

widget click to Esy payout

Path to conversion

page journey of recent converters, exact-attributed

Recent Conversions

Manual adjustments

revenue with no per-conversion CSV row, such as Esy's "3rd Party Aggregators" line
Add an adjustment

Added to the chosen day's totals. Re-entering the same site, date and label updates the amount.

Accounting — estimated vs. paid

Estimated = revenue we tracked (conversions). Paid = what you enter from your Esy statement. The difference surfaces scrubbing / bad-lead clawbacks. Negative = paid less than tracked. Click a Paid cell to edit.

AI Briefs

compiles the selected sites + period into a markdown report with an analysis prompt — copy it into Claude

      

Your account

Scan this with Google Authenticator, 1Password, or Authy, then enter the 6-digit code to turn on two-factor:

Or enter manually:

Users

Categories

Rank and rent sites show up under Landlord. Analytics-only sites stay on the traffic dashboard.

Sites

Assign a category. Rank-and-rent setup is under Landlord → Sites.
Tracker snippet (once per site, in head)

        

Import history from Plausible

Pulls day × page × source × device traffic from the Plausible Stats API into this dashboard as historical events. Then upload your old conversion CSVs in the Revenue tab — they'll attribute by page URL + date against the imported traffic. Safe to re-run (a range re-import replaces itself). Get an API key at plausible.io → Settings → API Keys.

Google Search Console

One Google login covers Search Console (day × page × query under Search → Google). Sign in as the account that owns the Search Console properties. No JSON keys, no OAuth Playground.

One site by hand after you are connected. Property URL looks like sc-domain:marketunlock.com (Domain property) or https://marketunlock.com/ (URL-prefix).

CSV fallback: Search Console → Performance → Export → Queries.csv or Pages.csv (powers top-queries / top-pages, not revenue-per-query).

Bing Webmaster Tools (revenue per query)

Bing is the bulk of these sites' search traffic. Pulls Bing's keywords, pages, and positions and joins them to revenue by landing page — shown under Search → Bing and in the Silos view. Bing returns a trailing snapshot, so each import replaces the last.

Automate it: in Bing Webmaster Tools → Settings → API access → generate an API key, then set it on the app service and redeploy. Every site in the dashboard is pulled daily (sites not verified in that Bing account are skipped with an error in the log).

railway variables --service app \
  --set "BING_API_KEY=your-bing-webmaster-api-key"

Optional: BING_IMPORT_HOURS (default 24, 0 = manual only), BING_SITES (comma list of verified site URLs, if you don't want every tracked domain).

One site by hand (key optional once BING_API_KEY is set). The site URL is the verified property, e.g. https://marketunlock.com.

Ringba call import

Pulls the Ringba call log on a schedule and books each inbound call onto the site from mua_domain, then RINGBA_CAMPAIGN_SITES, then RINGBA_SITE_DOMAIN. In Ringba: Settings → API Access Tokens → create a token, and copy your account id (starts with RA).

railway variables --service app \
  --set "RINGBA_API_TOKEN=your-ringba-api-token" \
  --set "RINGBA_ACCOUNT_ID=RAxxxxxxxxxxxxxxxxxxxx" \
  --set "RINGBA_CAMPAIGN_SITES=Campaign Name=drywallmeridian.com"

Optional: RINGBA_IMPORT_HOURS (default 1, 0 = manual only), RINGBA_LOOKBACK_DAYS (default 3), RINGBA_SITE_DOMAIN (fallback site), RINGBA_TARGETS (buyer allowlist; default is every buyer). Sites need the Ringba JS tag plus a number pool for exact attribution.

CSV Import History

Read-only API tokens

For spreadsheets, automation, and AI. A token allows GET requests to /api/* only (never writes). Send it as Authorization: Bearer <token> or append ?token=…. The token is shown once at creation — copy it then.

AI access (MCP): point Claude at <this app>/mcp with the token as a bearer header — e.g. claude mcp add marketunlock-analytics --transport http https://…/mcp --header "Authorization: Bearer mua_…". Claude then gets 20 read-only tools (stats, revenue, calls, funnel, search, vitals, …).

Bot cleanup

Bots are blocked two ways automatically: data-center IPs are rejected at ingest, and an auto-sweep every 20 minutes removes burst-pattern bot visitors (groups of direct, no-engagement visitors landing in the same minute). This button runs the same sweep manually over the selected site + date range — useful for cleaning up older data.