WordPress plugin · documentation

CryptoMeter

Self-hosted AI traffic control for WordPress. See which AI bots really are who they claim to be, what each company's bots take compared with the visitors it sends back, and apply one policy across robots.txt, AI licensing signals and your server. No account, no monthly fee, no visitor data leaves your site. Optional: let x402-capable AI agents pay per article.

Plugin version 1.0.0 WordPress 6.6+ PHP 7.4+ GPL-2.0-or-later Docs updated 2026-09-25

1.Overview and honest expectations

CryptoMeter runs inside your WordPress site. It watches every request from a bot or AI crawler (human visitors are never logged), checks whether the bot is genuine, applies the policy you choose, and shows the result in its own admin area under CryptoMeter in the WordPress sidebar.

What it does

  • Verified bot identity. Each bot request is checked against the vendor's official published IP list (OpenAI, Perplexity, Anthropic, Google, Microsoft), forward-confirmed reverse DNS (search engines and Google's AI crawlers), or a Web Bot Auth signature (RFC 9421, Ed25519, currently used by ChatGPT). Every request gets a verdict: Verified, Spoofed, Unverified or Unknown.
  • Activity log and live feed. Every bot request with bot, intent, verdict, decision, status code, bytes served, page and the network prefix of the IP (never the full address).
  • AI referral tracking. Visitors who click through from ChatGPT, Perplexity, Claude, Gemini, Copilot and five more assistants are counted per page and compared with how much each company's bots crawl (the crawl-to-visit ratio).
  • robots.txt violation detector. Flags requests for paths that the bot's own robots.txt group disallows.
  • One policy, every signal. From one screen: robots.txt Content-Signal, IETF Content-Usage (draft), RSL /license.xml, TDMRep /.well-known/tdmrep.json and optional noai tags, with a preview before you publish.
  • Policies per intent (Search engines, AI search & answers, AI agents, AI training) with per-bot exceptions and per-bot rate limits. Block is enforced by WordPress with HTTP 403 and written to robots.txt.
  • Server and cache rule snippets for Nginx, Apache, LiteSpeed, Cloudflare and WP Rocket, generated from your block list.
  • Weekly report and spike alert by e-mail, plus an HTTPS webhook.
  • Monetize (optional, off by default). Bots you set to Charge receive an HTTP 402 x402 payment request; x402-capable agents pay in USDC straight to your own wallet.
Honest expectations: please read this before you buy or go live
  • Signals are declarations, not protection. robots.txt, Content Signals, Content-Usage, RSL, TDMRep and noai tell bots what you allow. Bots that respect them follow them; others ignore them. What CryptoMeter enforces is the Block policy (HTTP 403) for requests that reach WordPress, plus any server rules you choose to install.
  • Referral counts are a lower bound. Many AI apps (and most mobile apps) hide where a visitor came from, so part of your AI traffic arrives as "direct" and cannot be counted.
  • Unverified does not mean spoofed. A bot whose company publishes no IP list, DNS or signature method can only be "Unverified". An IP that cannot be judged (private or proxy address, list not fetched yet, DNS failure) is "Unknown". Only a definite failed check is "Spoofed".
  • User agents can be faked, and bots that pose as normal browsers are not recognised as bots. CryptoMeter classifies by user agent (or signature) and then verifies; it is not a general bot-management firewall.
  • Page caches that answer before WordPress runs hide those requests from CryptoMeter. See Page caches.
  • Monetize is revenue-ready, not an income product. x402 is young and few AI agents pay today. No earnings are promised.

How a bot request flows

1 · RecogniseThe user agent (or a Web Bot Auth signature) names a known bot.
2 · VerifyOfficial IP list, reverse DNS or signature gives a verdict.
3 · DecideYour policy: Allow, Block (403), rate limit (429) or, with Monetize, Charge (402).
4 · LogOne row in the activity log. Humans are never logged.
5 · CompareThe referral beacon counts visitors sent back by AI assistants.

What is included, and what is not

IncludedNot included
  • The cryptometer WordPress plugin, with the compiled admin app (build/) and its source (admin-app/src/)
  • Translation template languages/cryptometer.pot
  • Self-test script tests/run-tests.php
  • Optional Node.js demo payment client tools/pay-demo.mjs (Monetize only)
  • This documentation
  • A CDN, firewall or hosted bot-management service
  • Detection of bots that pretend to be normal browsers
  • Installing server or page-cache configuration on your hosting (snippets are provided)
  • Custody of funds, private keys or seed phrases (Monetize)
  • A facilitator service, blockchain fees or facilitator fees (Monetize)
  • Any promise of earnings, legal or tax advice

Words used in this guide

TermMeaning
Bot / crawler / agentAutomated software that requests web pages: to train AI models, to build a search or AI-answer index, or to fetch a page because a person asked an assistant.
IntentWhat a bot is reading for: Search engines, AI search & answers, AI agents (user-triggered) or AI training. Generic HTTP clients appear as Other clients.
PolicyAllow, Block or (only with Monetize) Charge. Set per intent, with per-bot exceptions.
VerdictResult of the identity check: Verified, Spoofed, Unverified or Unknown (see Verification explained).
ReferralA human visit that arrived from an AI assistant (by referrer host or utm_source).
Crawl-to-visitA company's bot requests divided by the visitors its assistant sent you. 14 : 1 means 14 bot requests per referred visitor.
x402An open protocol that uses HTTP status 402 ("Payment Required") so software can pay for a web resource (x402.org). Only relevant to Monetize.

2.Requirements

ItemRequirementNotes
WordPress6.6 or newerThe admin app needs WordPress 6.6 (below it, the CryptoMeter page shows a notice; bot rules and signals keep working). Tested with WordPress 7.1.2.
PHP7.4 or newerVerified on PHP 7.4.33 and PHP 8.4.25 (WordPress Playground).
DatabaseThe normal WordPress databaseTables are created with the standard WordPress dbDelta API. All recorded test runs used SQLite in WordPress Playground. MySQL/MariaDB has not been tested yet, although it is the normal WordPress database.
BrowserA current browser with JavaScriptThe admin screens are a React app built on WordPress's own components.
PHP sodium extension (recommended)sodium_crypto_sign_verify_detachedNeeded to verify Web Bot Auth signatures (and Ed25519 Coinbase CDP keys). Present on most PHP 7.2+ hosts. Without it, signed requests fall back to IP/DNS checks.
Outbound HTTPSYour server can reach the official IP list URLsSee External services. If blocked, lists stay "Not fetched yet" and verdicts become "Unknown", never "Spoofed".
WP-CronWorking WP-Cron or a real cron jobDaily list refresh and pruning, hourly spike check, weekly report.
Pretty permalinks (recommended)Settings → Permalinks not "Plain"Needed for /llms.txt, /license.xml and /.well-known/tdmrep.json on most servers.
Page cacheMust let AI bots reach WordPressSee Page caches.
Monetize onlyA public EVM wallet address; outbound HTTPS to your facilitatorOptional. PHP DOM extension recommended (clean Markdown for paying agents). Node.js only for the demo client.

You can check most of these at any time under CryptoMeter → Settings → Tools & status → System status.

WordPress Multisite has not been fully tested. The uninstall routine cleans up every site in a network (code read, not run on a network). Activate the plugin per site and test on a staging copy first.

3.Quick start (10 minutes)

  1. Install and activate (Plugins → Add New Plugin → Upload Plugin → choose cryptometer.zip → Install Now → Activate). You land on CryptoMeter → Overview.
  2. Set up. In the Set up CryptoMeter card pick a preset. Get cited, block training is recommended and already active from the moment you activate. Leave Also let AI agents pay per read (optional) off unless you want Monetize. Press Apply and start.
  3. Load the official IP lists. Open Bots & rules → Verification sources and press Refresh now. Each list should show a green tick and a number of IP ranges. (They also refresh by themselves once a day.)
  4. Check your cache. Open Bots & rules → Server & cache rules, pick a published post and press Run loopback test. You want "WordPress answered the bot directly." If a cache is reported, see Page caches.
  5. Check it from a terminal (replace the address with one of your posts):
    curl -i -A "Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)" https://your-site.example/your-post/
    # With the default preset: HTTP/1.1 403 Forbidden and the header  x-cryptometer: block
    
    curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0" https://your-site.example/your-post/
    # A normal visitor: 200
    
    curl -s https://your-site.example/robots.txt
    # Shows "User-agent: GPTBot" / "Disallow: /" blocks and a Content-Signal line
    These three results were reproduced on a test install (WordPress 7.1.2, PHP 8.4.25).
  6. Wait for data. The Overview and Activity screens fill as real bots visit. Nothing is estimated or made up; empty screens say "No AI visits yet".

Testing tip. Logged-in users are never logged or blocked. Test with a terminal or a private browser window.

4.Installation

Your download from CodeCanyon contains the installable plugin ZIP. If you downloaded "All files and documentation", unzip it first and look for cryptometer.zip (the ZIP that contains the cryptometer folder with cryptometer.php inside).

Option A: upload in WordPress (easiest)

  1. Log in to WordPress as an administrator.
  2. Go to Plugins → Add New Plugin and click Upload Plugin.
  3. Choose cryptometer.zip and click Install Now.
  4. Click Activate Plugin.

Option B: upload by FTP / SFTP / file manager

  1. Unzip cryptometer.zip on your computer. You get a folder named cryptometer.
  2. Upload that folder to wp-content/plugins/ so that wp-content/plugins/cryptometer/cryptometer.php exists.
  3. In WordPress go to Plugins and click Activate under "CryptoMeter – AI Crawler Control & x402 Pay-per-Read".

What happens on activation

  • Four database tables are created: {prefix}cryptometer_log (bot activity log), {prefix}cryptometer_referrals (daily referral counters), {prefix}cryptometer_hits (daily traffic counters) and {prefix}cryptometer_payments (Monetize payment ledger).
  • Default settings are saved. The default policy Get cited, block training is enforced immediately: AI training crawlers get HTTP 403; search engines, AI search and user-triggered agents read normally. Monetize is off.
  • A random site secret is generated (used only by Monetize access passes).
  • The addresses /llms.txt, /license.xml and /.well-known/tdmrep.json are registered (the last two answer 404 until you turn them on under Signals).
  • Scheduled tasks are added (WP-Cron: daily, hourly, weekly) and a first download of the official IP lists is scheduled about a minute later.
  • You are redirected to CryptoMeter → Overview (unless you activated several plugins at once).

A CryptoMeter menu appears in the admin sidebar. It opens one page with the tabs Overview, Activity, Referrals, Bots & rules, Signals, Monetize and Settings. The Plugins screen gets a Dashboard link under the plugin name.

5.First run: setup and presets

Until setup is done, the Overview shows the Set up CryptoMeter card, and the WordPress Dashboard and Plugins screens show the notice "AI bot traffic is being logged. Pick how AI bots should be treated in one step." with a Finish setup link.

Set up CryptoMeter card with four preset choices, the optional Monetize toggle and a wallet address field
The setup card on the Overview (test install, here with the optional Monetize toggle switched on). Captured during development: the statistics cards under the setup card look different in the final version.
  1. Policy preset: choose one of the four presets below.
  2. Also let AI agents pay per read (optional): leave off for pure traffic control. If you switch it on, a field Your wallet address (EVM, public address only) appears. You can also add the wallet later under Monetize. Never paste a private key or seed phrase.
  3. Press Apply and start, or Skip for now (keeps the current settings and hides the card).

Presets

A preset sets the policy of each intent and, except for Monitor only, the published search / AI input / AI training preferences (robots.txt Content-Signal, Content-Usage, RSL, TDMRep), so the signals say the same thing the server does. Block all AI publishes ai-input=no, ai-train=no; the other presets publish ai-input=yes, ai-train=no. You can fine-tune everything later on Bots & rules and Signals.

PresetSearch enginesAI search & answersAI agents (user-triggered)AI trainingExceptions
Get cited, block training (default)AllowAllowAllowBlockBytespider: Block
Block all AIAllowBlockBlockBlocknone
Monitor onlyAllowAllowAllowAllownone
Charge training and agents (needs Monetize)AllowAllowChargeChargeBytespider: Block

Applying a preset replaces the intent policies and removes per-bot exceptions. Rate limits and custom bots are kept. The Charge preset can only be chosen while Monetize is on.

6.Overview

CryptoMeter → Overview answers three questions: who is reading, is it real, and what comes back. All numbers come from your own database; there is no sample data.

Overview screen with status band, KPI cards, AI traffic chart, Who is reading table, By intent bars and Most-read posts
Overview of a test install with a few scripted test requests (sent from 127.0.0.1, which is why verification shows "Unknown"). Your numbers will differ.

Status band

Protection active ("Every AI bot request is checked, logged and handled by your policy."), Protection paused (CryptoMeter is switched off under Settings → General) or Setup needed. Below it: the current Policy (preset name, or "Custom policy"), Verification lists (for example "8 of 8 fresh"), Last AI visit and Monetize (Off, On · Test mode, On · Live). If a page-cache plugin is detected, a warning links to Open server & cache rules.

Cards (7, 30 or 90 days, UTC days)

CardExact meaning
AI requestsEvery logged bot request except genuine search engines: AI crawlers and agents, generic HTTP clients (curl, python-requests and similar), and search-engine user agents that failed verification. Sub-line: allowed and rate-limited.
VerificationShare verified, with counts for Verified, Spoofed, Unverified and Unknown.
BlockedRequests turned away by your policy (HTTP 403).
Visitors from AIReferred visitors counted by the beacon, with the overall crawl-to-visit ratio. A minimum, see Referrals.
Earned (only with Monetize)USDC from settled payments; "paid" and "asked to pay" counts.
Ignored robots.txt (without Monetize)Requests for URLs your robots.txt disallows for that bot; sub-line: bytes served to bots.

Chart and tables

  • AI traffic: daily AI requests, blocked requests and visitors from AI, "Collecting since" the first logged request. Show as table shows the same data as a table.
  • Who is reading: per AI company, Bot requests, Visitors sent and Crawl : visit. Inactive companies are hidden behind Show all.
  • By intent: requests per intent with the current policy; Change policy opens Bots & rules.
  • Most-read posts: the content AI bots request most, and which of it brings visitors back.

7.Activity

CryptoMeter → Activity lists every request from an AI bot or crawler. Human visitors and logged-in users are never logged, and IP addresses are shortened to their network prefix (IPv4 /24, IPv6 /48).

Activity table with filters for bot, company, intent, verification and decision, and columns time, bot, intent, verification, decision, status, size, page and robots.txt
Activity in table view (test install, scripted requests from 127.0.0.1). The Page column shows the path and the IP prefix.
  • View: Feed or Table. Live polls for new requests every 5 seconds ("Updating every 5 s"), paused while the browser tab is hidden.
  • Filters: search (path, bot or post), Bot, Company, Intent, Verification, Decision, and Ignored robots.txt only. Clear all filters resets them.
  • Columns: Time, Bot (and company), Intent, Verification (verdict and method), Decision, Status (HTTP code), Size (bytes sent), Page, robots.txt (Ignored or Respected).

Decisions

LabelMeaning
AllowedThe bot read the page (policy Allow).
BlockedHTTP 403 (policy Block, per-post block, or spoofed bot).
Rate-limited (429)Over a per-bot limit, or (Monetize) the per-IP limit for unpaid requests.
Passed (search)A search engine; passes untouched.
Free by ruleAn access rule made the read free (allowlisted IP or user agent, excluded path or category, short post, daily free reads).
Asked to pay (402), Paid, Access pass, Payment failed, Not charged (no wallet)Monetize only. See The HTTP 402 flow.

The log keeps 90 days by default (Settings → General → Retention).

8.Referrals

CryptoMeter → Referrals shows visitors who arrive from AI assistants, compared with how much each company's bots read.

Referrals screen with the lower-bound notice, a daily chart, the Take vs. give back table, Share of visitors and Posts that bring visitors from AI
Referrals on a test install with one test referral from ChatGPT.

How visitors are counted

  • A tiny inline script (under 1 KB) runs on the front end for visitors who are not logged in. It only sends something when the referrer host or the utm_source parameter matches a known AI assistant.
  • It posts the page path, the assistant host and the utm_source value to /wp-json/cryptometer/v1/beacon with navigator.sendBeacon. Because the visitor's browser sends it, it also works when the page itself came from a page cache.
  • No cookies, no IP address stored, no personal data. Only day × assistant × post counters are saved. A salted hash of the IP is kept for 2 minutes to limit one visitor to 30 beacons per minute.
  • Switch it off under Settings → General → Count visitors from AI assistants.

Recognised assistants

AssistantReferrer host / utm_sourceCompared with the bots of
ChatGPTchatgpt.com, chat.openai.comOpenAI (all OpenAI bots)
Perplexityperplexity.aiPerplexity
Claudeclaude.aiAnthropic
Geminigemini.google.comGoogle's AI bots only (GoogleOther, Google-CloudVertexBot), not Googlebot
Copilotcopilot.microsoft.comMicrosoft (the only Microsoft bot in the list is Bingbot)
You.comyou.comYou.com (YouBot)
DeepSeekchat.deepseek.comno known crawler: ratio n/a
Meta AImeta.aiMeta
Mistralchat.mistral.aiMistral
Grokgrok.comno known crawler: ratio n/a

Take vs. give back lists visitors, bot requests and Crawl : visit per assistant ("Lower is better"). The ratio shows n/a when there are no visitors yet or no known crawler. On low-traffic sites the ratio is noisy; look at the raw counts too.

9.Bots & rules

CryptoMeter → Bots & rules has three sections: Policies, Verification sources and Server & cache rules.

Policies

Bots and rules Policies tab with the preset bar, four intent cards with Allow, Block and Charge, individual bot tables with policy and rate limit, and the Everything else card
Policies (test install with Monetize on and one custom bot, "NewAIBot"). The help text under "Custom AI user agents" in this screenshot comes from a development build; the final text says custom bots appear in the AI training group, which matches where NewAIBot is listed.
  • Start from a preset: the four presets from section 5. A confirmation dialog explains what is replaced.
  • Intent cards: one per intent (Search engines, AI search & answers, AI agents (user-triggered), AI training) with Allow / Block / Charge, requests in the last 30 days, number of bots and exceptions.
    • Charge is locked until Monetize is on. A stored Charge policy acts as Allow while Monetize is off ("Charge acts as Allow until Monetize is on.").
    • Blocking search engines shows "This removes your site from search results."
    • Blocking AI search & answers can mean fewer citations in AI search tools.
  • Individual bots: one table per intent with Verification method, Last seen, Requests (30 d), Spoofed (30 d), Policy (Inherit (…), Allow, Block, Charge) and Rate limit (requests per minute; empty or 0 = no limit). Reset exceptions to inherit removes the group's exceptions.
  • Everything else:
    • Generic HTTP clients: Treat as humans (default), Block or Charge. Covers python-requests, curl, Go-http-client, Scrapy, headless Chrome, empty user agents and similar libraries. Many anonymous scrapers use these, but so do some legitimate tools (uptime monitors, feed readers).
    • Block spoofed bots (default on): requests that claim to be a known bot but fail verification are blocked.
    • Custom AI user agents: one user-agent fragment per line (at least 3 characters). After saving they appear in the AI training group, where you can set their policy.

Press Save changes in the bar at the bottom. "Bot policies saved. robots.txt and signals are updated." confirms it.

Per-bot rate limits

A per-bot limit counts all requests of that bot per minute, across all its IP addresses. Above the limit the bot gets HTTP 429 with Retry-After: 60 and the text "Too many requests from this crawler. Slow down." It applies on every page, whatever the bot's policy. Verified on a test install: with a limit of 3, requests 4 and 5 in the same minute returned 429.

Command palette

Where WordPress provides its command palette (Ctrl/⌘ + K), the CryptoMeter page adds commands such as "CryptoMeter: Overview", "CryptoMeter: Bots & rules", "CryptoMeter: Settings" and "CryptoMeter: Block AI training bots".

Verification sources

Verification sources with three toggles, eight official IP lists with IP range counts, the signed-request agent chatgpt.com and the list of bots verified by reverse DNS
Verification sources on a test install after "Refresh now" (range counts as fetched on 2026-09-24; they change when vendors update their lists).
  • Check official IP lists, Check signed requests (Web Bot Auth) and Verify search engines by reverse DNS switch each method on or off (all on by default).
  • The table shows each list's vendor and URL, the number of IP ranges and when it was last updated. A red dot shows the fetch error; the last good copy is kept.
  • Refresh now downloads all lists and the key directory immediately. Otherwise they refresh once a day by WP-Cron.
  • Signed-request agents: origins whose Web Bot Auth keys are trusted (default https://chatgpt.com), with key count and age.
  • Verified by reverse DNS: googleother, google-vertex, googlebot, bingbot, applebot, yandexbot, baiduspider.

How verdicts are decided is explained in section 14.

Server & cache rules

Server and cache rules with tabs Nginx, Apache (.htaccess), LiteSpeed, Cloudflare and WP Rocket, a generated snippet with a Copy button, and the Loopback test
Server & cache rules (test install). The snippet is generated from the bots your policy currently blocks.

CryptoMeter's own blocking happens inside WordPress. Blocking at the web server or CDN saves PHP work, and excluding AI bots from page caches lets CryptoMeter see, verify and log them. The snippets are regenerated each time you open the tab ("Update them after you change policies").

TabWhat it containsWhere it goes
NginxReturns 403 for blocked user agents (except /robots.txt) and sets fastcgi_cache_bypass / fastcgi_no_cache for all AI user agents.Inside the server { } block of the site; then reload Nginx.
Apache (.htaccess)mod_rewrite rule answering 403 ([F]) for blocked user agents, except /robots.txt..htaccess, above # BEGIN WordPress.
LiteSpeedThe Apache rule plus a LiteSpeed Cache no-cache rule for AI user agents..htaccess, above # BEGIN WordPress.
CloudflareA WAF custom rule expression matching blocked user agents, excluding /robots.txt.Cloudflare dashboard → Security → WAF → Custom rules: paste as the expression, action Block.
WP RocketAll AI user-agent fragments, one per line.WP Rocket → Advanced Rules → "Never Cache User Agent(s)".

Test before and after. A mistake in server configuration can take a site down. Keep a backup of the file you edit, and test with the curl commands from the Quick start. Server-level rules block by user agent only (no verification), and requests stopped there never reach WordPress, so they do not appear in Activity. The snippets were generated and read on a test install; MIKODES has not run them on a live Nginx, Apache, LiteSpeed or Cloudflare setup.

The Loopback test at the bottom is explained in Simulator and loopback test and Page caches.

Built-in bot list

A bot is recognised when its match fragment appears in the request's User-Agent (case-insensitive). ChatGPT agent uses a normal Chrome user agent and is recognised only by its Web Bot Auth signature. Listing a company here only means CryptoMeter recognises its crawler; it says nothing about whether it pays through x402.

BotCompanyIntentMatchVerification
GPTBotOpenAIAI trainingGPTBotOfficial IP list
OAI-SearchBotOpenAIAI search & answersOAI-SearchBotOfficial IP list
ChatGPT-UserOpenAIAI agentsChatGPT-UserOfficial IP list, signature
ChatGPT agentOpenAIAI agents(signature only)Signed request
ClaudeBotAnthropicAI trainingClaudeBotOfficial IP list
Claude-SearchBotAnthropicAI search & answersClaude-SearchBotOfficial IP list
Claude-UserAnthropicAI agentsClaude-UserOfficial IP list
anthropic-aiAnthropicAI traininganthropic-aiOfficial IP list
PerplexityBotPerplexityAI search & answersPerplexityBotOfficial IP list
Perplexity-UserPerplexityAI agentsPerplexity-UserOfficial IP list
GoogleOtherGoogleAI trainingGoogleOtherOfficial IP list, reverse DNS
Google-CloudVertexBotGoogleAI agentsGoogle-CloudVertexBotOfficial IP list, reverse DNS
Meta-ExternalAgentMetaAI trainingmeta-externalagentNo method
Meta-ExternalFetcherMetaAI agentsmeta-externalfetcherNo method
FacebookBotMetaAI trainingFacebookBotNo method
AmazonbotAmazonAI search & answersAmazonbotNo method
BytespiderByteDanceAI trainingBytespiderNo method
CCBotCommon CrawlAI trainingCCBotNo method
cohere-aiCohereAI agentscohere-aiNo method
cohere-training-data-crawlerCohereAI trainingcohere-training-data-crawlerNo method
MistralAI-UserMistralAI agentsMistralAI-UserNo method
DuckAssistBotDuckDuckGoAI search & answersDuckAssistBotNo method
YouBotYou.comAI search & answersYouBotNo method
DiffbotDiffbotAI trainingDiffbotNo method
AI2BotAllen InstituteAI trainingAI2BotNo method
TimpibotTimpiAI trainingTimpibotNo method
omgiliWebz.ioAI trainingomgiliNo method
ImagesiftBotHiveAI trainingImagesiftBotNo method
GooglebotGoogleSearch enginesGooglebotOfficial IP list, reverse DNS
BingbotMicrosoftSearch enginesbingbotOfficial IP list, reverse DNS
ApplebotAppleSearch enginesApplebotReverse DNS
DuckDuckBotDuckDuckGoSearch enginesDuckDuckBotNo method
YandexBotYandexSearch enginesYandexBotReverse DNS
BaiduspiderBaiduSearch enginesBaiduspiderReverse DNS

That is 28 AI crawlers and agents and 6 search engines, plus your custom user agents. A request that carries an x402 payment or access-pass header but matches no known bot is recorded as "x402 client".

10.Signals

CryptoMeter → Signals ("Signals & licensing") tells AI companies, in their own formats, what they may do with your content. As the screen says: signals are requests, not locks; Bots & rules is what enforces them.

Signals and licensing screen with Search, AI answers and AI training yes/no choices, format toggles and a live preview of robots.txt
Signals with the default choices (test install). The preview shows exactly what is published. The "# CryptoMeter: AI access to this site is metered with x402" comment lines appear only because Monetize was on in this test install.

What may AI do with your content?

ChoiceMeaningDefault
SearchBuild a search index and show links and short snippets.Yes
AI answersUse your content as input for AI answers (RAG, grounding).Yes
AI trainingTrain or fine-tune AI models on your content.No

Formats

ToggleWhat is publishedDefault
Content-Signal line in robots.txtA User-agent: * group in the virtual robots.txt with Content-Signal: search=yes, ai-input=yes, ai-train=no (contentsignals.org, CC0).On
Content-Usage (IETF aipref) Draft standardContent-Usage: train-ai=n, ai-use=y, search=y in the same robots.txt group and as an HTTP response header on front-end pages. The IETF syntax is a draft and may still change.On
RSL licence (license.xml)An RSL 1.0 document at /license.xml, a License: line at the top of robots.txt and a Link: <…/license.xml>; rel="license"; type="application/rsl+xml" header. Extra fields: Licence terms and Licensing contact (e-mail or URL, optional).Off
TDMRep (EU text & data mining reservation)/.well-known/tdmrep.json, a tdm-reservation: 1 header and meta tag, and optionally a TDM policy URL (tdm-policy).Off
noai / noimageai meta tags Experimental<meta name="robots" content="noai, noimageai"> and an X-Robots-Tag: noai, noimageai header. Not officially supported by Google or OpenAI; some smaller crawlers read it.Off

RSL licence terms

  • Search and AI answers allowed, AI training prohibited (default)
  • All AI use prohibited (search indexing allowed)
  • Follow the search / AI answers / AI training choices above
  • Free reuse with attribution and a link
  • AI use needs a licence: contact me
  • Pay per crawl with x402 (Monetize): only offered while Monetize is on; if Monetize is off or not set up, the default terms are published instead.

Output verified on a test install with RSL on and a contact address:

<?xml version="1.0" encoding="UTF-8"?>
<rsl xmlns="https://rslstandard.org/rsl">
  <content url="/">
    <license>
      <prohibits type="usage">ai-train</prohibits>
      <legal type="contact">mailto:licensing@example.com</legal>
    </license>
  </content>
</rsl>

The Preview (tabs robots.txt, license.xml, tdmrep.json, HTTP headers) updates as you change options ("Unsaved — this is what will be published after you save."). Press Save changes; "Signals saved and published." confirms it.

Physical robots.txt. If a real robots.txt file exists in your web root, the web server serves it and WordPress's virtual robots.txt (with CryptoMeter's lines) is never used. The preview then shows your physical file. Either delete the file or copy the lines into it by hand.

robots.txt, /license.xml and /.well-known/tdmrep.json stay readable for every bot, including blocked ones. Signal lines, headers and files are only published while CryptoMeter is switched on (Settings → General).

11.Monetize (optional)

CryptoMeter → Monetize: "Optional: let x402-capable AI agents pay per article in USDC, straight to your own wallet. Few agents pay today — treat it as an extra, not a revenue plan." Everything else in CryptoMeter works without it.

Monetize screen with the Pay-per-read for AI agents toggle, earnings cards and an empty payments ledger
Monetize switched on, in Test mode, on a test install (no payments yet).

Turning it on

  1. Switch Pay-per-read for AI agents on.
  2. Enter your wallet under Payments and save. Until a valid wallet is saved, bots set to Charge are let through and counted as unpaid demand.
  3. Choose which bots pay: on Bots & rules set an intent or a bot to Charge, or apply the preset Charge training and agents.
  4. Stay in Test mode and use the Simulator first.

Non-custodial. CryptoMeter stores only your public wallet address. The paying agent signs the transfer and a facilitator you choose settles it on-chain. CryptoMeter never asks for a private key or seed phrase; anyone asking you for one "to set up CryptoMeter" is a scammer.

Switching Monetize off makes Charge behave like Allow again (logged as "Allowed"). Your wallet, prices and ledger are kept.

Payments

Payments card with wallet address, Test and Live mode, test network, live networks, facilitator choices and protocol options
Payments card (test install, "Custom facilitator URL" selected to show its fields).
FieldWhat it doesDefault
Wallet address (receives USDC) pay_toYour public EVM address (0x + 40 hex characters). Payments go straight here. An invalid address is not saved.empty
Mode modeTest: testnet USDC, no real money. Live: real USDC on mainnet. Payments and traffic counters are recorded per mode.Test
Test network network_testBase Sepolia, Polygon Amoy, Arbitrum Sepolia or Avalanche Fuji.Base Sepolia
Live networks networks_liveBase, Polygon, Arbitrum One, Avalanche C-Chain. Agents may pay on any network you tick. Only tick networks your facilitator supports. If none is ticked, Base is used.Base
Facilitator facilitatorx402.org — free, testnet only · PayAI — mainnet & testnet, no API key · Coinbase CDP — mainnet, your CDP API key · Custom facilitator URL. Choosing Live with x402.org switches to PayAI automatically, with a notice.x402.org
Facilitator URL, Bearer token (optional)Custom only. The URL must be https:// (plain http only for localhost, 127.0.0.1, ::1). The token is sent as Authorization: Bearer … and never shown again ("Saved — type to replace").empty
CDP API key ID, CDP API key secretCoinbase CDP only. Replaced by "CDP credentials are defined in wp-config.php." when the constants are set.empty
Check facilitator (saved settings)Tests the saved settings (save first). Shows "Facilitator reachable" / "Facilitator not reachable", "API key accepted" / "API key rejected" (CDP), "This facilitator is testnet-only. Choose another one for live mode.", and per network: supported, not supported by this facilitator, or unknown.-
Also accept x402 v1 clients (X-PAYMENT header) legacy_v1Accept the older v1 header and send a v1-shaped body next to the v2 header. Recommended.On
Payment timeout max_timeoutSeconds a signed payment may take (sent as maxTimeoutSeconds). 30-600.120

Pricing and per-post prices

Pricing card with content types, flat or per 1,000 words price, minimum and maximum, fresh content, archive, training multiplier and access window
Pricing card (test install with example values, not the defaults).
FieldWhat it doesDefault
Content types post_typesWhich public post types are metered (published, not password-protected). This also decides where the editor box, the per-post "Blocked" option and the core REST API guard apply.Post
Flat per article / Per 1,000 wordsPricing model.Flat
Price per article / Price per 1,000 wordsUSDC, 0-100.0.01 / 0.005
Minimum, MaximumComputed prices are raised to the minimum or capped at the maximum (0 = no cap). Per-post custom prices are not clamped.0.001 / 1.00
Fresh content: charge × … for the first … daysPremium for new posts. 0 days = off.× 2, off
Archive: … % of the price after … daysDiscount for old posts. 0 days = off. Skipped when the post is fresh.50 %, off
Training crawlers pay ×Extra multiplier for AI training bots.× 1
After paying, the same article stays open for … hoursAccess window (0 = pay every read, max 8760).24

Price calculation order

  1. Per-post setting (editor): Read for free → 0; Blocked → 403; custom price → used as-is.
  2. Category price: the highest CryptoMeter price among the post's categories.
  3. Otherwise the site model (flat, or words ÷ 1,000 × price per 1,000 words).
  4. Fresh premium or archive price (only one).
  5. Training multiplier for AI training bots.
  6. Minimum / maximum.
  7. The cryptometer_price filter has the final say.

Per post and per category

  • Editor box "CryptoMeter · AI access" (sidebar of metered post types), "AI bots reading this post": Pay site price (default), Pay a custom price (Price per read (USDC)), Read for free, Blocked. Blocked works with or without Monetize: AI bots get HTTP 403 for that post; humans and search engines are unaffected. The box shows the current price and, once there are payments, "Earned $X from N paid AI reads".
  • Posts list: an "AI price" column (a price, Free or Blocked).
  • Posts → Categories: field AI price per read (USDC) overrides the site price for posts in that category. Only the standard Categories taxonomy has it.

The HTTP 402 flow

For developers and the curious. You do not need this to use the plugin.

  1. Challenge. A bot set to Charge requests a metered post and gets HTTP 402 Payment Required with a PAYMENT-REQUIRED header (x402 v2, base64 JSON: resource plus one accepts entry per active network with scheme: "exact", CAIP-2 network, amount in atomic units, USDC contract, payTo, maxTimeoutSeconds, token name/version), a JSON body (v1 shape when v1 is accepted) with a cryptometer object (title, teaser, price, networks, message), and Link: </llms.txt>; rel="describedby". Verified on a test install: GPTBot with the Charge preset got 402, x-cryptometer: challenge, amount 10000 (0.01 USDC) on base-sepolia.
  2. Pay. The agent signs a USDC TransferWithAuthorization (EIP-3009) for exactly that amount to your address and retries with PAYMENT-SIGNATURE (v2) or X-PAYMENT (v1).
  3. Check and settle. CryptoMeter checks locally (decoding, version, network, exact amount, token, recipient, validity window, unused nonce), throttles failed attempts (10 per IP per minute), calls the facilitator's /verify, reserves the nonce (replay protection) and calls /settle (one retry on "pending").
  4. Deliver. HTTP 200 with PAYMENT-RESPONSE (v1: X-PAYMENT-RESPONSE) and the article as HTML, Markdown or JSON (see What paying agents receive). With an access window: X-CryptoMeter-Access (access pass) and X-CryptoMeter-Access-Expires.

Every non-search response CryptoMeter changes carries Cache-Control: no-store, private, max-age=0, Vary: User-Agent, Accept, PAYMENT-SIGNATURE, X-PAYMENT, the X-CryptoMeter decision header and the DONOTCACHEPAGE constant.

The access pass is a bearer token. Whoever holds it can re-open that one article until it expires. Set the access window to 0 to charge every read. To invalidate all passes: wp option delete cryptometer_secret (a new secret is created automatically).

Back doors. With Monetize set up and "Show bots set to Charge only excerpts in RSS feeds and the REST API" on, charged bots see excerpts only in feeds, archive/home/search pages and /wp-json/wp/v2/… for metered post types.

Networks and facilitators

NetworkCAIP-2 idv1 nameUSDC contract
Baseeip155:8453base0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Base Sepolia (testnet)eip155:84532base-sepolia0x036CbD53842c5426634e7929541eC2318f3dCF7e
Polygoneip155:137polygon0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359
Polygon Amoy (testnet)eip155:80002polygon-amoy0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582
Arbitrum Oneeip155:42161(none)0xaf88d065e77c8cC2239327C5EDb3A432268e5831
Arbitrum Sepolia (testnet)eip155:421614(none)0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d
Avalanche C-Chaineip155:43114avalanche0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E
Avalanche Fuji (testnet)eip155:43113avalanche-fuji0x5425890298aed601595a70AB815c96711a31Bc65
FacilitatorURLModeKey
x402.orghttps://x402.org/facilitatorTest onlynone
PayAIhttps://facilitator.payai.networkTest and livenone
Coinbase CDPhttps://api.cdp.coinbase.com/platform/v2/x402Liveyour CDP key
Customyour URL (/verify, /settle, /supported under it)Test and liveoptional bearer token

Facilitators are independent third parties with their own terms, availability and possible fees. CryptoMeter does not operate one and takes no fee. Trust your facilitator: CryptoMeter checks amount, recipient, network, expiry and replay itself, but relies on the facilitator for signature validity and settlement.

Coinbase CDP key in wp-config.php (recommended)

// Ed25519 key (one line)
define( 'CRYPTOMETER_CDP_KEY_ID', 'your-cdp-key-id' );
define( 'CRYPTOMETER_CDP_KEY_SECRET', 'your-base64-ed25519-secret' );

// or an EC (PEM) key: keep the line breaks as \n inside double quotes
define( 'CRYPTOMETER_CDP_KEY_SECRET', "-----BEGIN EC PRIVATE KEY-----\nLINE1\nLINE2\n-----END EC PRIVATE KEY-----\n" );

Create the key at portal.cdp.coinbase.com. Ed25519 needs the PHP sodium extension; PEM (ES256) needs openssl. A CDP API key lets your site call the facilitator; it cannot move funds from your receiving wallet. Keep it secret anyway.

Test payment and demo client

The Monetize card Make a real test payment summarises this. tools/pay-demo.mjs is a small Node.js x402 client; WordPress never loads it.

Use a throwaway testnet wallet only. The demo needs a private key to sign. Never use the key of a wallet that holds real funds, and never your receiving wallet's key. CryptoMeter itself never needs a private key.

  1. On a staging copy: Monetize on, Test mode, Base Sepolia, x402.org, your receiving wallet saved, and the test bot set to Charge (the Simulator must show 402 for GPTBot). Do not send a login cookie: logged-in users are never charged.
  2. Install Node.js (a current LTS; the demo was verified with Node.js 22). Copy the plugin's tools folder to your computer and run npm install inside it (installs viem).
  3. Dry run with a random, empty wallet: node pay-demo.mjs https://staging.example.com/some-post/. Expected: a 402, then a retry answered with the facilitator error invalid_exact_evm_insufficient_balance (the random wallet has no USDC). That proves the chain works.
  4. Create a throwaway wallet (inside tools):
    node --input-type=module -e "import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; const k = generatePrivateKey(); console.log('PRIVATE_KEY=' + k); console.log('ADDRESS=' + privateKeyToAccount(k).address);"
  5. Get free testnet USDC for that address at faucet.circle.com (USDC, Base Sepolia).
  6. Pay: PRIVATE_KEY=0xYOUR_THROWAWAY_TESTNET_KEY node pay-demo.mjs https://staging.example.com/some-post/. On success it prints ← 200 OK, the decoded PAYMENT-RESPONSE, the access-pass expiry and the start of the article in Markdown; the payment appears in the ledger.
VariablePurposeDefault
PRIVATE_KEYThrowaway testnet key. Without it a random empty wallet is used.random
UAUser agent sent to your site.Mozilla/5.0 (compatible; GPTBot/1.2; x402-demo)
ACCEPTAccept header (Markdown / JSON / HTML).text/markdown
COOKIEOptional Cookie header (for example a staging password page). Not a WordPress login cookie.none

Status. MIKODES verified the unfunded dry run against the real x402.org facilitator and the full success path against a mock facilitator (2026-09-23). A settlement with funded testnet USDC has not been recorded, so step 6 describes what the client prints according to its code.

Earnings and ledger

  • Earned (settled payments only), Paid reads, Paying wallets, Unpaid demand ("Value of AI requests that were asked to pay and did not. Not money you are owed — just demand."), for 7/30/90 days, labelled Test data or Live data according to the current mode.
  • Payments ledger: When, Post, Bot, Payer (masked), Network, Amount, Status (Settled, Pending, Processing, Unconfirmed, Failed), Transaction (explorer link).
  • Export CSV downloads all payments of the current mode as cryptometer-<mode>-<date>.csv with full payer addresses (columns created_at_utc, post_id, url, bot, payer, network, asset, amount_atomic, amount_usdc, status, tx_hash, x402_version, facilitator). Cells starting with = + - @ are prefixed with an apostrophe.
  • Recent facilitator errors appears when verify/settle calls failed. A few failures are normal (agents without funds).

Only Settled payments count as earned. Unconfirmed means the facilitator returned a transaction hash but still reported pending after one retry; no content was served; check the explorer. Rows stuck in Processing for over an hour are marked failed by the daily task. Tax treatment of crypto income depends on your country; ask a professional.

Simulator and loopback test

See your site through an AI bot's eyes (Monetize screen): choose a post and a visitor (GPTBot, ClaudeBot, PerplexityBot, ChatGPT-User, Googlebot, Human visitor or any bot under "All bots") and press Simulate request. You see the verdict (for example "403 GPTBot → Blocked with HTTP 403", or a 402 with the price), the Price breakdown, a ready curl command (Try it from a terminal), the Decoded PAYMENT-REQUIRED header and the Response body the bot receives. The simulation uses a made-up request: no facilitator call, no statistics, your IP is ignored and the rate limit is skipped.

Loopback test (Monetize screen and Bots & rules → Server & cache rules): Run loopback test makes your server request the post's normal URL with a GPTBot user agent and reports the status and the X-CryptoMeter header.

  • "WordPress answered the bot directly. The page cache is not in the way." — good.
  • "The bot got a 200 without passing through CryptoMeter. A page cache is probably serving AI bots." — see Page caches.

Avoid false warnings. Run it on a published item of a metered content type (Posts by default), with CryptoMeter switched on. With the default preset GPTBot is blocked, so a working setup answers 403 with X-CryptoMeter: block. If GPTBot is allowed and you test a Page that is not a metered content type, WordPress sends no X-CryptoMeter header and the test wrongly suspects a cache. Some hosts block a server from requesting itself; then the test shows an error.

12.Settings

CryptoMeter → Settings has five tabs. Each card saves on its own with Save changes. The grey key names are the internal names in the settings export file (option cryptometer_settings).

General

Settings General tab with the Protection toggle, referral counting toggle and log retention
Settings → General (test install).
FieldWhat it doesDefault
Apply bot policies and log AI traffic enabledMaster switch ("CryptoMeter on this site"). When off, every request passes through untouched, nothing is logged, and the admin header shows Paused. Note: the robots.txt lines, signal headers, /license.xml and /tdmrep.json are also only published while this is on. /llms.txt is not affected.On
Count visitors from AI assistants referral_trackingThe referral beacon (see Referrals).On
Keep logs for … days log_retention_daysBot log rows older than this are deleted daily. The small daily counters (traffic and referrals) keep at least 365 days. Payment records are always kept. 7-3650.90

Access rules

Settings Access rules tab with always allowed IPs and user agents, never restricted paths and categories, limits and messages
Settings → Access rules (test install with Monetize on, so the Monetize-only fields are visible).

The screen describes these as "Exceptions that apply before any bot policy." In practice a Block policy still wins (an allowlisted IP using a blocked bot's user agent is still blocked); the rules make reads free for bots that would otherwise be charged.

FieldWhat it doesDefault
IP addresses and ranges allow_ipsOne IP or CIDR per line (IPv4 and IPv6). Invalid lines are dropped on save.empty
User agents allow_uasUser-agent fragments, one per line. User agents can be faked; prefer IP rules for anything valuable.empty
URL paths exclude_pathsOne path per line, * as wildcard (for example /press/*).empty
Categories exclude_categoriesPosts in these categories are free for AI.none
Posts under … words min_wordsShort posts are free. 0 = off.0
Payment requests per IP per minute rate_limitHTTP 429 with Retry-After: 60 above the limit. This per-IP limit only counts unpaid requests from bots set to Charge (Monetize on and set up). Allowed bots are not counted by it. To slow down any bot, use the per-bot rate limits. 0 = off.60
Free reads per bot per day bot_daily_free (Monetize)Metered articles each bot may read free per UTC day before charging. 0 = off.0
Blocked bots (HTTP 403) block_messagePlain-text body for blocked bots. Empty = "Automated AI access to this content is not permitted by the publisher."empty
Payment required (HTTP 402) challenge_message (Monetize)Message in the 402 body. Placeholders {price} {networks} {title} {site} {url}.empty

Content & discovery

Settings Content and discovery tab with robots.txt and llms.txt toggles, the back doors toggle and the paying-agents options
Settings → Content & discovery (test install with Monetize on).
FieldWhat it doesDefault
Write your bot policy to robots.txt robots_syncAdds User-agent: … / Disallow: / for every AI bot whose policy is Block (never for search engines), plus a comment line pointing to /llms.txt. Signal lines are controlled under Signals.On
Publish /llms.txt llms_txtA plain-text overview (llmstxt.org style): site name and tagline, an "AI access and licensing" section, a link to the free JSON catalog and your 30 latest articles (posts set to Blocked are left out). Off = 404.On
Show bots set to Charge only excerpts in RSS feeds and the REST API protect_feedsFor bots set to Charge (Monetize set up): excerpts only in feeds, archives and /wp-json/wp/v2/…. Bots set to Block are refused on feeds (403) and get empty content from the core REST API whether or not this is on.On
What paying agents receive serve_format (Monetize)Automatic (Markdown if the agent sends Accept: text/markdown, JSON for application/json without text/html, otherwise the page), Always clean Markdown, or Always the normal HTML page.Automatic
Teaser in the 402 response teaser_words (Monetize)Words of preview in the 402 body and in excerpts. 0-500.60
Announce articles to x402 Bazaar discovery bazaar (Monetize)Adds the x402 "bazaar" extension to the challenge. Whether a facilitator lists your site is up to it.Off
Service name shown to agents service_name (Monetize)Up to 32 ASCII characters, sent as serviceName.empty
Show "AI access licensed via x402" under posts badge (Monetize)Badge under metered posts (only when payments are set up); or place [cryptometer_badge] anywhere.Off

Notifications

Settings Notifications tab with recipient, weekly report, spike alert, daily summary, payment e-mail and webhook
Settings → Notifications (test install, example values).
FieldWhat it doesDefault
Send to notify_emailRecipient. Empty = the site admin address.empty
Weekly AI traffic report notify_weeklyOnce a week (WP-Cron): AI bot requests, verified, spoofed, blocked, visitors referred by AI assistants (visible referrer only), the crawl-to-referral ratio and the top 5 companies (bot requests / referrals). Not sent in a week without AI requests or referrals.Off
Alert me when AI traffic spikes spike_alert, spike_factorChecked every hour: an e-mail is sent when the last hour had at least 50 AI requests and more than the factor × the average hour of the previous 7 days. At most one alert per 6 hours. (The on-screen wording talks about a day; the code compares hours.) Factor 2-100.Off, × 5
Daily summary notify_digestYesterday's numbers (UTC): earned, paid reads, AI bot visits, blocked, unpaid demand. Only sent on days with AI activity.Off
E-mail me every time an AI agent pays notify_each (Monetize)One e-mail per settled payment.Off
Webhook URL webhook_urlAn https:// URL that receives a JSON POST after every settled payment (Monetize). See Webhooks.empty
Signing secret (optional) webhook_secretAdds X-CryptoMeter-Signature: sha256=…. Masked after saving.empty
Send test event (saved URL)Sends an event of type test and shows "Webhook delivered · HTTP …" or the error.-

E-mails use WordPress's wp_mail(). If you do not receive them, your site may need an SMTP plugin.

Tools & status

Settings Tools and status tab with system status rows, export and import settings, and erase data options
Settings → Tools & status (test install; the red Facilitator row is because a custom facilitator without a URL was selected for the screenshot).
  • System status: PHP, WordPress, sodium, DOMDocument, Pretty permalinks, Database tables, Daily maintenance (WP-Cron), Wallet address and Facilitator (only with Monetize), Page cache (detected plugins), Cloudflare (only when the request came through Cloudflare). Green = OK, amber = check, red = problem.
  • Export settings → Download JSON. API secrets (CDP secret, bearer token, webhook secret) are never exported.
  • Import settings: choose a .json file and press Import. Only known settings are imported and validated; secrets on this site are kept; the page reloads. A file from another plugin is rejected ("That is not a CryptoMeter settings file.").
  • Erase data: Test-mode payments and test traffic · Bot request log (Activity) · Referral counters · All statistics (log, referrals and daily counters). Press Delete…, tick "I understand this cannot be undone" and press Delete permanently. Live payments are accounting records and cannot be deleted here.

CryptoMeter also adds suggested text to Settings → Privacy → Policy Guide describing the bot log and the referral beacon.

wp-config.php constants

CryptoMeter has no .env file. Everything is in the admin screens, plus these optional constants (above /* That's all, stop editing! */):

ConstantPurposeWhere to get the value
CRYPTOMETER_CDP_KEY_IDCoinbase CDP API key ID (Monetize). Overrides the stored value.portal.cdp.coinbase.com
CRYPTOMETER_CDP_KEY_SECRETCoinbase CDP key secret (base64 Ed25519 or EC PEM).Shown once when you create the key
CRYPTOMETER_DELETE_LEDGERSet to true before deleting the plugin to also remove the payment ledger and per-post/category prices.Your decision

13.How a request is handled

For front-end requests (pages, posts, archives, feeds, search) that reach WordPress, in this order:

  1. CryptoMeter switched off, admin, AJAX, previews, or a logged-in user → untouched, not logged.
  2. robots.txt, /license.xml, /.well-known/tdmrep.json → always served.
  3. Classification by user agent (or Web Bot Auth signature) and verification. Not a known bot and not a generic client → human: untouched, not logged.
  4. Policy Block (including spoofed bots while "Block spoofed bots" is on) → 403, site-wide.
  5. Over the bot's per-bot rate limit → 429.
  6. Search engine → passes. AI bot on a post (of a metered type) set to Blocked in the editor → 403. Policy Allow → reads normally.
  7. Policy Charge (Monetize): access rules → price → no wallet yet (let through, counted as unpaid demand) → access pass → per-IP limit for unpaid requests → 402 or payment processing.
VisitorResponseX-CryptoMeter
Human, logged-in user, generic client (default)200, normal pagenone
Search engine (verified, or check undecided)200, normal pagenone
AI bot set to Allow (on a post of a metered type)200, normal pagefree
Blocked bot, spoofed bot, or post set to Blocked403 with your block messageblock
Over a rate limit429, Retry-After: 60limited
Bot set to Charge (Monetize set up)402 + x402 challengechallenge
Agent that paid or has a valid access pass200 + contentpaid

Verified on a test install with the default preset: GPTBot 403 (block), Bytespider 403, ChatGPT-User 200 (free), normal browser 200, curl's default user agent 200. A spoofed search-engine user agent never gets the search-engine pass; with "Block spoofed bots" off it is treated like a generic HTTP client.

14.Verification explained

VerdictWhen
VerifiedThe IP is in the vendor's official list, or forward-confirmed reverse DNS matches the vendor's domain, or the request carries a valid Web Bot Auth signature from a trusted agent.
SpoofedThe bot has a verification method and the check definitely failed: the IP is in none of the (fresh) lists and reverse DNS does not confirm it, or reverse DNS gives a definite mismatch, or a signature is invalid for a bot without an IP list.
UnverifiedThe bot publishes no way to verify it (no list, no DNS, no signature), or you switched the methods off.
UnknownThe check could not decide: private or proxy IP, list not fetched yet or older than 3 days, DNS failure, or the DNS lookup budget (30 new lookups per minute) is used up.
  • Official IP lists are downloaded once a day (and with Refresh now), with a 10-second timeout and a 1 MB limit each, and stored with fetch time, count and status. On failure the last good copy is kept. A list older than 3 days is never used to call a request "Spoofed".
  • Reverse DNS: the host name of the IP must end with the vendor's domain (for example .googlebot.com, .search.msn.com, .applebot.apple.com) and resolve back to the same IP. Results are cached per IP for a day.
  • Web Bot Auth (RFC 9421 HTTP Message Signatures, Ed25519): headers Signature, Signature-Input and Signature-Agent. Keys come from https://chatgpt.com/.well-known/http-message-signatures-directory, cached a day. Only allow-listed agents are fetched (filter cryptometer_signature_agents). Needs PHP sodium.
  • No verification download happens during a visitor's request; lists and keys are fetched in the background.
  • Behind a proxy or CDN, verification needs the real visitor IP: see Cloudflare and proxies. Local test requests (127.0.0.1) always show "Unknown".

Verified on a test install: Refresh now fetched all eight lists (18, 39, 229, 8, 4, 26, 317 and 28 ranges on 2026-09-24) and one key from chatgpt.com. Verified/spoofed verdicts for real crawler IPs are covered by the self-test with in-memory lists, not by live crawler traffic.

15.Page caches

A full-page cache can answer a request before WordPress and CryptoMeter run. The bot is then not verified, not logged and not blocked. This is the most common setup problem, so please check it.

What CryptoMeter already does

  • Every response it changes (403, 429, 402, allowed AI bot on a metered post, paid content) sets DONOTCACHEPAGE and sends Cache-Control: no-store, private, max-age=0 and Vary: User-Agent, Accept, PAYMENT-SIGNATURE, X-PAYMENT.
  • It detects WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, SiteGround Speed Optimizer, Breeze, Cache Enabler, Hummingbird and WP_CACHE, and warns on the Overview, in System status and on Server & cache rules.
  • The referral beacon is sent by the visitor's browser, so referrals are counted even on cached pages.

This stops CryptoMeter's responses from being cached, but it cannot stop a cache from serving a page that was cached earlier for a human.

What you configure

  1. Open Bots & rules → Server & cache rules and use the snippet for your cache: WP Rocket (Never Cache User Agents list), LiteSpeed (no-cache rule), Nginx (FastCGI cache bypass). For other caches (Varnish, host-managed caches, Cloudflare APO), exclude or bypass requests whose User-Agent contains the fragments from the WP Rocket tab, or vary the cache on User-Agent. Ask your host if unsure.
  2. With Monetize, also never answer requests carrying PAYMENT-SIGNATURE, X-PAYMENT or X-CryptoMeter-Access from cache.
  3. Clear all caches, run the loopback test again, and check from outside with the curl command from the Quick start (expect 403 and x-cryptometer: block for GPTBot with the default preset).

Search engines pass anyway, so a cache serving them does no harm, except that a fake "Googlebot" served from cache is not detected.

16.Cloudflare and proxies

CryptoMeter needs the visitor's real IP for verification, IP allowlists, rate limits and the IP prefix in the log.

Cloudflare: automatic

When a request comes from a Cloudflare edge address (ranges from cloudflare.com/ips, built in as of 2026-09-23) and carries CF-Connecting-IP, that header is used as the visitor IP. Requests from other addresses cannot fake it. The Cloudflare row in System status confirms it. If another proxy sits in front of Cloudflare, or Cloudflare publishes new ranges, use a must-use plugin:

  1. Create wp-content/mu-plugins/ if it does not exist.
  2. Create a file, for example cryptometer-custom.php, starting with <?php, and add the snippet. Must-use plugins load automatically.
<?php
// Always trust CF-Connecting-IP (only if ALL traffic reaches your server through Cloudflare).
add_filter( 'cryptometer_trust_cloudflare', '__return_true' );

// Add a range Cloudflare publishes later.
add_filter( 'cryptometer_cloudflare_ranges', function ( $ranges ) {
	$ranges[] = '198.51.100.0/24'; // example
	return $ranges;
} );

Other proxies and load balancers

<?php
// Behind your own load balancer or reverse proxy (not Cloudflare).
add_filter( 'cryptometer_client_ip', function ( $ip ) {
	$trusted_proxies = array( '10.0.0.5' ); // the address(es) of YOUR proxy
	$remote          = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
	if ( in_array( $remote, $trusted_proxies, true ) && ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
		$parts = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
		$first = trim( $parts[0] );
		if ( filter_var( $first, FILTER_VALIDATE_IP ) ) {
			return $first;
		}
	}
	return $ip;
} );

Never trust X-Forwarded-For from everyone: any client can send it and pretend to be an allowlisted IP or a verified bot.

17.Webhooks and signatures

After every settled Monetize payment CryptoMeter sends a JSON POST to your webhook URL (Settings → Notifications). Only https://; private and internal addresses are refused (WordPress "safe" HTTP API); redirects are not followed; sent in the background with a short timeout and not retried (use the ledger or CSV as the source of truth). Headers: Content-Type: application/json, User-Agent: CryptoMeter/1.0.0, X-CryptoMeter-Event (payment.settled or test) and, with a secret, X-CryptoMeter-Signature: sha256=<hex>.

{
  "event": "payment.settled",
  "id": "423618ba-fa43-48b0-b59e-4d8acd8b362b",
  "created_at": "2026-09-23T09:59:28+00:00",
  "mode": "test",
  "site": "https://your-site.example/",
  "post": { "id": 4, "title": "Your post", "url": "https://your-site.example/your-post/" },
  "amount_usdc": "0.01",
  "network": "eip155:84532",
  "network_label": "Base Sepolia (testnet)",
  "transaction": "0x...",
  "explorer": "https://sepolia.basescan.org/tx/0x...",
  "payer": "0x...",
  "bot": "GPTBot",
  "bot_type": "training"
}

The test button sends "event": "test". The weekly report and spike alert are e-mail only; they are not sent to the webhook.

Verify the signature

HMAC-SHA256 of the raw body with your secret, in hex, prefixed with sha256=. Compare in constant time.

<?php
// webhook-receiver.php on YOUR server (not inside WordPress).
$secret   = getenv( 'CRYPTOMETER_WEBHOOK_SECRET' );
$body     = file_get_contents( 'php://input' );
$sent     = isset( $_SERVER['HTTP_X_CRYPTOMETER_SIGNATURE'] ) ? $_SERVER['HTTP_X_CRYPTOMETER_SIGNATURE'] : '';
$expected = 'sha256=' . hash_hmac( 'sha256', $body, $secret );
if ( ! hash_equals( $expected, $sent ) ) {
	http_response_code( 401 );
	exit( 'bad signature' );
}
$event = json_decode( $body, true );
http_response_code( 200 );
echo 'ok';
// receiver.mjs (Node.js, no dependencies)
import http from 'node:http';
import crypto from 'node:crypto';
const SECRET = process.env.CRYPTOMETER_WEBHOOK_SECRET;
http.createServer( ( req, res ) => {
	const chunks = [];
	req.on( 'data', ( c ) => chunks.push( c ) );
	req.on( 'end', () => {
		const raw = Buffer.concat( chunks );
		const expected = 'sha256=' + crypto.createHmac( 'sha256', SECRET ).update( raw ).digest( 'hex' );
		const sent = String( req.headers[ 'x-cryptometer-signature' ] || '' );
		const ok = sent.length === expected.length &&
			crypto.timingSafeEqual( Buffer.from( sent ), Buffer.from( expected ) );
		if ( ! ok ) { res.writeHead( 401 ).end( 'bad signature' ); return; }
		const event = JSON.parse( raw.toString( 'utf8' ) );
		console.log( event.event, event.amount_usdc, event.transaction );
		res.writeHead( 200 ).end( 'ok' );
	} );
} ).listen( 8787 );

Both receivers were tested against a signature produced by the plugin's code in the earlier verification round (2026-09-23); the signing code is unchanged in this version.

18.Public files and REST API

Public files

AddressWhenContent
/robots.txtAlways (WordPress virtual robots.txt; site visible to search engines)Your robots.txt plus Disallow blocks for blocked bots, Content-Signal / Content-Usage lines and, with RSL, a License: line.
/llms.txtPublish /llms.txt onPlain text, cached 1 hour. Workaround under plain permalinks: /?cryptometer_llms=1.
/license.xmlRSL onapplication/rsl+xml, otherwise 404.
/.well-known/tdmrep.jsonTDMRep onJSON, otherwise 404.

Verified on a test install: /llms.txt 200; /license.xml and /.well-known/tdmrep.json 404 by default and 200 after switching them on.

REST API

Namespace /wp-json/cryptometer/v1 (with plain permalinks: /?rest_route=/cryptometer/v1/…).

RouteAccessPurpose
GET /catalogpublicMachine-readable list of articles (page, per_page 1-100, search). payments.enabled is false and prices are 0.00 while Monetize is not set up.
GET /articles/{id}public, always meteredMonetize's paid article API: 402 → pay → JSON. 404 cryptometer_not_found, 403 cryptometer_blocked (post set to Blocked), 503 cryptometer_disabled (CryptoMeter off). Editors of the post get it free.
POST /beaconpublicReferral beacon; always answers 204.
/admin/*administrators (manage_options + REST nonce); anonymous calls get 401Power the admin screens (overview, activity, activity/live, referrals, bots, verification, verification/refresh, signals, signals/preview, rules, settings, monetize, privacy/erase, simulate, facilitator, webhook-test, live-test). Not meant for external use.

Core WordPress REST API: for bots set to Block, /wp-json/wp/v2/… of metered post types returns empty content; for charged bots (Monetize) a teaser with content.protected: true and content.x402 pointing to the paid endpoint.

19.External services and privacy

CryptoMeter contacts these services. No data about your visitors is sent. Requests identify themselves as CryptoMeter/<version> (WordPress; <your site URL>). Every request has a timeout, and a failure never affects your visitors (the last good copy is kept).

ServiceWhenWhat is sentSwitch
Official bot IP lists:
openai.com/gptbot.json
openai.com/searchbot.json
openai.com/chatgpt-user.json
www.perplexity.ai/perplexitybot.json
www.perplexity.ai/perplexity-user.json
claude.com/crawling/bots.json
developers.google.com/static/crawling/ipranges/common-crawlers.json
www.bing.com/toolbox/bingbot.json
Once a day by WP-Cron, shortly after activation/update, and on "Refresh now"A plain GET (your site URL is in the User-Agent)Check official IP lists (turning it off stops the lists being used; the daily download still runs)
Web Bot Auth key directory https://chatgpt.com/.well-known/http-message-signatures-directoryAt most once a day (daily refresh, or after a signed request when the cached keys are older than a day)A plain GETCheck signed requests (Web Bot Auth)
Reverse DNSWhen an IP claims to be a search engine or a Google AI bot; cached a day; max 30 new lookups a minuteThe IP, to your server's own DNS resolverVerify search engines by reverse DNS
x402 facilitator (Monetize only)When an agent pays, and when you press Check facilitatorThe agent's payment payloadMonetize off
Your webhook URL (only if set)After a settled payment, and the test buttonThe payment eventLeave empty

Terms: those of each vendor's or service's website. The admin app and this documentation load no external fonts or scripts.

What is stored

WhereWhat
{prefix}cryptometer_logOne row per bot request: time, bot, intent, verdict, method, decision, status, bytes, post, path (max 255 characters), IP network prefix (IPv4 /24, IPv6 /48), robots.txt violation flag, mode. Never humans. 90 days by default.
{prefix}cryptometer_referralsDay × assistant × post counters. No IP, no cookie.
{prefix}cryptometer_hitsDaily counters per post, bot and outcome. No IP.
{prefix}cryptometer_paymentsMonetize payments (payer wallet address, amount, network, transaction, status and so on).
Optionscryptometer_settings (secrets masked in forms, never exported), cryptometer_secret, cryptometer_errors, cached IP lists cryptometer_iplist_* and key directories cryptometer_sigdir_* (not autoloaded).
Transients cryptometer_*Rate-limit counters (hashed keys, about 2 minutes), reverse-DNS results per IP hash (1 day), cached robots.txt rules (1 hour).

An IP network prefix and a payer wallet address can count as personal data in some jurisdictions; mention them in your privacy policy if that applies to you (see the suggested text under Settings → Privacy).

20.Developer hooks

Put customisations in a must-use plugin (how) or your own plugin, never in CryptoMeter's files.

HookArgumentsUse it to
cryptometer_botsarray $bots keyed by id: name, vendor, match, type (training, search_ai, agent, search), optional policy, rdns, signature_agentAdd or change bots
cryptometer_generic_clientsstring[]Change the generic HTTP client list
cryptometer_ip_sourcesarray id => {vendor, url, bots[]}Add or change official IP lists
cryptometer_ip_list_max_ageint seconds (default 3 days)How old a list may be to call a miss "Spoofed"
cryptometer_signature_agentsstring[] origins (default https://chatgpt.com)Trust more Web Bot Auth agents
cryptometer_rdns_per_minuteint, default 30Reverse-DNS lookup budget
cryptometer_referral_vendorsarray id => {label, hosts[], bot_vendor, bots[]|null}Add AI assistants for referral counting
cryptometer_beacon_per_minuteint, default 30Beacon limit per visitor
cryptometer_log_requestbool $log, array $clientSkip logging for some requests
cryptometer_spike_min_hitsint, default 50Minimum hourly requests for a spike alert
cryptometer_content_usagestring $value, array $configAdjust the Content-Usage value if the IETF draft changes
cryptometer_license_xmlstring $xml, array $configChange the RSL document
cryptometer_llms_txtstringChange /llms.txt
cryptometer_client_ip, cryptometer_trust_cloudflare, cryptometer_cloudflare_rangessee section 16Real visitor IP
cryptometer_pricefloat $usd, int $post_idFinal price (Monetize)
cryptometer_networks, cryptometer_facilitators, cryptometer_facilitator_request_args, cryptometer_max_failed_payments, cryptometer_licensesee the code commentsMonetize networks, facilitator presets, facilitator request args, failed-payment throttle (default 10 per IP per minute), licence line in paid content
cryptometer_payment_settled (action)$post_id, $settle, $client, $quoteReact to a settled payment

Examples

<?php
/**
 * Plugin Name: CryptoMeter customisations
 */

// 1. Recognise an extra AI crawler (appears in the AI training group).
add_filter( 'cryptometer_bots', function ( $bots ) {
	$bots['examplebot'] = array(
		'name'   => 'ExampleBot',
		'vendor' => 'Example Inc.',
		'match'  => 'ExampleBot', // case-insensitive user-agent substring
		'type'   => 'training',   // training | search_ai | agent | search
	);
	return $bots;
} );

// 2. Do not log requests to a health-check URL.
add_filter( 'cryptometer_log_request', function ( $log, $client ) {
	$uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
	return false === strpos( $uri, '/healthz' ) ? $log : false;
}, 10, 2 );

// 3. Count visits from another AI assistant.
add_filter( 'cryptometer_referral_vendors', function ( $vendors ) {
	$vendors['example'] = array(
		'label'      => 'Example AI',
		'hosts'      => array( 'chat.example.ai' ),
		'bot_vendor' => 'Example Inc.', // compare with bots of this vendor
		'bots'       => null,           // or an explicit list of bot ids
	);
	return $vendors;
} );

// 4. Add a section to /llms.txt.
add_filter( 'cryptometer_llms_txt', function ( $txt ) {
	return $txt . "\n## Licensing contact\n\nlicensing@example.com\n";
} );

Hook names and arguments were checked against the code. Examples 2 and 3 were reviewed, not run. The referral beacon script lists the vendor hosts when the page is rendered, so a vendor added with the filter is included automatically.

21.Security model

  • All admin screens and /admin/* REST routes require manage_options and a WordPress REST nonce; export/import use admin nonces.
  • Outbound requests use the WordPress safe HTTP API with timeouts and size limits; verification data is fetched in the background, never during a visitor's request.
  • Full visitor IPs are not stored; the log keeps the network prefix only.
  • Signature verification only fetches key directories of allow-listed agents; unknown or invalid signatures fall back to IP/DNS checks.
  • Monetize is non-custodial: public wallet address only; exact amount, recipient, network, validity and replay checks (unique nonce) before the facilitator; failed-payment throttle; CSV formula neutralisation.
  • User agents can be faked. Unverifiable bots can only be judged by user agent; bots that pose as browsers are not recognised. Use IP rules for partners. Logged-in users are never blocked, logged or charged, so do not give AI companies WordPress accounts.

22.Customization

CryptoMeter is a WordPress plugin, so there is no app name, bundle ID or icon set to change. The admin follows your WordPress admin colour scheme. What you can customise:

WhatHow
Which bots are allowed or blockedBots & rules (presets, intents, per-bot exceptions, custom user agents), cryptometer_bots
Text blocked bots seeSettings → Access rules → Blocked bots (HTTP 403)
Licensing signalsSignals; cryptometer_content_usage, cryptometer_license_xml
/llms.txtSettings → Content & discovery; cryptometer_llms_txt
Monetize texts402 message, service name, badge (style .cryptometer-badge in your theme), cryptometer_license
Admin languageTranslation

Do not edit the plugin's files; changes are lost on update. The admin app source is in admin-app/src/ and compiles to a single bundle in build/ with npm install and then npm run build inside admin-app (@wordpress/scripts). You only need this if you change the source; this build step was not re-run for this documentation.

23.Deployment checklist

  1. Install on staging first if you can. Run the self-test.
  2. Choose a preset and review the intent cards. Remember that blocking AI search & answers can reduce AI citations.
  3. Press Refresh now on Verification sources; all lists should be green.
  4. Page cache: loopback test plus an outside curl check; install the cache snippet if needed.
  5. Optional: server/CDN rules from Server & cache rules (back up the config first).
  6. Signals: decide on RSL, TDMRep and noai; check the preview; make sure no physical robots.txt hides the virtual one.
  7. Turn on the weekly report (and spike alert) under Notifications.
  8. Update your privacy policy with the suggested text.
  9. Monetize only: Test mode with the Simulator and ideally one demo payment on staging; then Mode Live, live networks, PayAI / Coinbase CDP / your facilitator (x402.org is testnet only), Check facilitator (saved settings), and watch the ledger and facilitator errors in the first days. Do not leave Test mode running on production: bots set to Charge would receive testnet challenges that cannot earn anything.

Staging to production: Settings → Tools & status → Download JSON on staging, Import on production. Secrets are not included; re-enter them or use the wp-config constants.

24.Updating

  1. Download the new version from your CodeCanyon downloads page.
  2. Recommended: Settings → Tools & status → Download JSON, and back up your database.
  3. Plugins → Add New Plugin → Upload Plugin → choose the new cryptometer.zip → Install Now → Replace current with uploaded. (Or overwrite wp-content/plugins/cryptometer by FTP.)
  4. Database and settings changes are applied automatically on the next page load.

Do not delete the plugin in order to update it. Deleting runs the uninstall routine, which removes settings, the activity log and statistics.

Coming from an earlier CryptoMeter build (pay-per-read layout)

If your site ran a pre-release build with the older screens (Dashboard, Payments, AI Bots, Simulator, Setup wizard), settings are migrated once: if a wallet was set, Monetize is switched on and AI agents and training crawlers stay on Charge; otherwise the default "Get cited, block training" applies. Existing per-bot choices are kept as exceptions. Old admin bookmarks (page=cryptometer-payments, -bots, -settings, -simulator, -setup) redirect to the matching new screen.

25.Self-test

CryptoMeter ships with a self-test that checks pricing, bot classification, intents and presets, IP-list verification, Web Bot Auth signatures (with a locally generated key), the robots.txt parser, signals output, referral vendors, rule snippets, header decoding, access passes, settings sanitisation, CDP JWT signing and the 402 decision engine. It makes no network calls; settings, IP lists and keys are overridden in memory only and never saved; the temporary posts and categories it creates are deleted at the end (or on shutdown if interrupted).

It needs WP-CLI (many hosts provide it over SSH). From your WordPress folder, with the plugin active (a staging copy is ideal):

wp eval-file wp-content/plugins/cryptometer/tests/run-tests.php

Expected output:

CryptoMeter self-test: 173/173 passed

Failures are listed as FAIL <name>. Verified result: 173/173 on WordPress 7.1.2 with PHP 8.4.25 (WordPress Playground, SQLite, 2026-09-24; the file was included through a local test harness rather than WP-CLI). The 173/173 result on PHP 7.4.33 is reported by the build team and was not re-run for this documentation. If you added your own cryptometer_price or cryptometer_bots filters, they still apply during the test, so some checks may report different values.

26.Deactivate and uninstall

Deactivate

Stops everything immediately: no blocking, no logging, no signals. Scheduled tasks are removed; settings and data stay, so you can reactivate at any time.

Delete (uninstall)

Deleting the plugin from the Plugins screen removes (on every site of a multisite network):

  • Options cryptometer_settings, cryptometer_secret, cryptometer_errors, cryptometer_db_version, cryptometer_spike_sent, cryptometer_rewrite_version
  • Tables {prefix}cryptometer_log, {prefix}cryptometer_referrals, {prefix}cryptometer_hits
  • Cached IP lists and key directories, scheduled tasks and cryptometer_* transients

It keeps the payment ledger ({prefix}cryptometer_payments) and per-post/category prices, because the ledger is your accounting record. To delete them too, add this before deleting the plugin (export a CSV first if you need the records):

define( 'CRYPTOMETER_DELETE_LEDGER', true );

After uninstalling, remove any server or CDN rules you copied from Server & cache rules; they live in your server configuration, not in WordPress.

27.Troubleshooting

Where to look: Activity (what happened to each request), Settings → Tools & status, Bots & rules → Verification sources, the loopback test, and the X-CryptoMeter response header.

No AI visits appear

  • Normal on a new or small site: AI bots visit irregularly. The screens say "Collecting since …".
  • A page cache serves the bots (run the loopback test, see Page caches), or a CDN/firewall rule stops them before WordPress.
  • CryptoMeter is paused (Settings → General).
  • You tested while logged in.

Everything shows "Unknown"

  • Lists not fetched yet: press Refresh now. If a list shows an error, your host may block outgoing HTTPS; ask it to allow the URLs in section 19.
  • Your site is behind a proxy/CDN and sees the proxy's (often private) IP: configure the real visitor IP.
  • WP-Cron does not run (low traffic or DISABLE_WP_CRON), so lists become older than 3 days. Set up a real cron job for wp-cron.php.

A genuine bot shows "Spoofed"

  • Your server sees a wrong IP (proxy): fix the visitor IP first.
  • The vendor's list changed after the last refresh: press Refresh now.
  • Your own SEO tool uses a search-engine user agent: switch off "Block spoofed bots" for it to be treated as a generic client, or give it its own user agent.

A bot I blocked still reads my pages

  • Page cache (most common).
  • The bot is not recognised (browser-like user agent) or uses a user agent not in the list: add it under Custom AI user agents.
  • A per-bot exception overrides the intent policy.
  • It reads files outside WordPress (images, static files). CryptoMeter only sees requests WordPress handles; use the server rules.

Referrals stay at 0

  • Referral counting is off (Settings → General), or you tested while logged in.
  • The assistant hid the referrer (common in apps). Test with https://your-site.example/?utm_source=chatgpt.com in a private window.
  • A script blocker, strict Content Security Policy or JavaScript optimisation plugin removes inline scripts, or a security plugin blocks /wp-json/cryptometer/v1/beacon.

robots.txt does not show CryptoMeter's lines

  • A physical robots.txt file exists in the web root (the Signals preview shows it). Remove it or edit it by hand.
  • Settings → Reading → "Discourage search engines" is ticked (site not public), or CryptoMeter is paused.
  • An SEO plugin replaces the robots.txt output entirely.

/llms.txt, /license.xml or /tdmrep.json return 404

  • The feature is off.
  • Plain permalinks: choose any other structure under Settings → Permalinks and save (this also refreshes rewrite rules). For llms.txt, /?cryptometer_llms=1 works as a workaround.
  • A physical file or a server rule for .txt, .xml or .well-known takes precedence.

HTTP 429 for a bot

A per-bot rate limit (Bots & rules), or with Monetize the per-IP limit for unpaid requests or the failed-payment throttle. All send Retry-After: 60. Behind a proxy without the real IP, all visitors share one IP.

The admin shows an error

  • "The server did not answer with JSON…" or "Your session has expired.": reload the page and log in again; a security plugin or a PHP error may have interrupted the request.
  • "The admin app is missing (build/ folder)": re-install the plugin from the original ZIP.
  • "The CryptoMeter dashboard needs WordPress 6.6 or newer": update WordPress.
  • "Database tables: missing" or "Daily maintenance: not scheduled" in System status: deactivate and activate the plugin.

E-mails do not arrive

Check the recipient and that your site can send mail (SMTP plugin). The weekly report and daily summary are skipped in periods without AI activity; the spike alert needs at least 50 requests in an hour.

Monetize problems

CodeHTTPMeaning and fix
invalid_exact_evm_insufficient_balance402The paying wallet lacks USDC on that network (normal for unfunded wallets).
invalid_exact_evm_signature402Signature not valid for this payment; the agent must sign again with the values from the challenge.
nonce_already_used402Replay protection: sign a new payment.
too_many_failed_payments429More than 10 failed verifications from this IP in a minute.
invalid_payment_requirements, …_recipient_mismatch, …_value_mismatch402Amount, network, token or recipient differ from the offer (for example the price changed). Request again.
…_valid_before / …_valid_after402Expired or not yet valid; check the agent's clock.
invalid_payload, invalid_x402_version400Malformed header, or v1 while v1 is not accepted.
network_error: …502Facilitator unreachable from your server.
settlement_pending402Still pending after one retry; the ledger row is Unconfirmed.
cdp_credentials_missing, cdp_key_invalid_pem, cdp_key_invalid_ed25519, cdp_sodium_missing-Coinbase CDP key problems; re-enter the key (PEM line breaks as \n), check sodium in System status.
facilitator_not_configured-"Custom facilitator URL" selected without a URL.
  • Bots set to Charge get 200 instead of 402: Monetize off, no valid wallet, post type not ticked under Content types, free by an access rule or price 0, or a page cache.
  • Wallet will not save: exactly 0x + 40 hex characters, no ENS names.
  • "This facilitator is testnet-only": x402.org cannot be used in Live mode.

28.FAQ

Does this hurt my Google ranking?

Not with the default settings. Search engines are allowed, fake search bots are detected by the official IP lists and DNS, and humans are never touched. Blocking the "Search engines" intent would remove your site from search results; the screen warns you.

Does blocking training crawlers stop my content from being used for AI?

It stops the bots CryptoMeter recognises from reading pages that reach WordPress, and tells well-behaved crawlers not to crawl (robots.txt) and not to train (signals). It cannot stop bots that disguise themselves as browsers, content copied elsewhere, or data collected before you installed it.

Does robots.txt stop AI bots?

Only the ones that respect it. CryptoMeter writes the rules, enforces Block with HTTP 403, and shows which bots requested disallowed URLs (Ignored robots.txt).

Why are my referral numbers so low?

Many AI apps hide the referrer, so the numbers are a minimum. They are still useful for comparing companies and posts over time.

Does any data leave my site?

No visitor data. CryptoMeter downloads public IP lists and a public key directory, asks your server's DNS resolver about bot IPs and, with Monetize, talks to your facilitator when an agent pays. See External services.

Do I need Monetize or a crypto wallet?

No. Monetize is off by default; everything else works without it.

Which AI companies pay today?

Any client that implements x402 can pay. Large crawlers mostly do not pay yet. We make no earnings promises.

Where does the money go, and does the plugin hold funds?

Straight to the wallet you enter, as USDC on the network the agent chose. The agent signs, the facilitator submits, your wallet receives. The plugin stores only your public address.

Can I let one AI company in (for example a licensing partner)?

Set that bot to Allow on Bots & rules. With Monetize, you can also add its IP ranges under Access rules so it reads free.

Does it work with my page cache or CDN?

Yes, if the cache lets AI bots reach WordPress. Use the snippets and the loopback test.

What happens to my data if I remove the plugin?

Settings, log and statistics are deleted; the payment ledger is kept unless you set CRYPTOMETER_DELETE_LEDGER.

29.Translation

CryptoMeter is translation-ready. Text domain: cryptometer. The template languages/cryptometer.pot contains 734 strings, from the PHP code and from the admin app.

  1. Open the .pot file in Poedit or a plugin such as Loco Translate and create a translation for your language.
  2. Save it as cryptometer-<locale>.po / .mo (for example cryptometer-de_DE.mo). The admin app additionally needs WordPress's JSON translation file for its script, which Loco Translate or wp i18n make-json creates from the .po file.
  3. Upload the files to wp-content/languages/plugins/ (survives plugin updates).

The JSON step follows the standard WordPress mechanism for script translations; a translated admin app was not verified by the documentation author.

Some texts that bots receive (403/402 messages, llms.txt, licence lines) are translated too, so bots see them in your site language. Override them under Access rules or with the filters.

30.Changelog

1.0.0 (first public release)

  • Verified bot identity: official IP lists (OpenAI, Perplexity, Anthropic, Google, Microsoft), forward-confirmed reverse DNS, Web Bot Auth signatures; Verified / Spoofed / Unverified / Unknown verdicts; Block spoofed bots.
  • Activity log with live feed, filters and robots.txt violation detector.
  • AI referral tracking for 10 assistants with crawl-to-visit ratios.
  • Policies per intent with presets, per-bot exceptions and per-bot rate limits.
  • Signals: Content-Signal, IETF Content-Usage (draft), RSL license.xml, TDMRep, noai, with preview.
  • Server & cache rule snippets (Nginx, Apache, LiteSpeed, Cloudflare, WP Rocket) and loopback test.
  • Weekly report, spike alert, daily summary, webhook.
  • React admin (Overview, Activity, Referrals, Bots & rules, Signals, Monetize, Settings).
  • Optional Monetize module: x402 v2 with v1 compatibility, USDC on Base, Polygon, Arbitrum and Avalanche, four facilitator options, pricing rules, ledger and CSV, simulator.

31.Credits and licences

  • CryptoMeter plugin (PHP, CSS, JavaScript in the cryptometer folder): © MIKODES, GPL-2.0-or-later (gnu.org/licenses/gpl-2.0.html). No third-party PHP libraries.
  • Admin app: built with @wordpress/scripts on WordPress's own packages (@wordpress/element, @wordpress/components, @wordpress/i18n, @wordpress/api-fetch, loaded from WordPress core at runtime) plus @wordpress/icons 17.0.0, which is bundled into build/index.js. All GPL-2.0-or-later.
  • Standards implemented from their public specifications: Content Signals (contentsignals.org, CC0), IETF aipref drafts (Content-Usage), RSL 1.0 (rslstandard.org), W3C TDMRep, RFC 9309 (robots.txt), RFC 9421 (HTTP Message Signatures) / Web Bot Auth, and the x402 specification (x402.org) for Monetize.
  • Optional demo client tools/pay-demo.mjs depends on viem (MIT) and its MIT-licensed dependencies, downloaded by npm install and never loaded by WordPress. Full list in THIRD-PARTY-LICENSES.
  • Screenshots in this documentation are real CryptoMeter admin screens from a MIKODES test installation (WordPress Playground) with test data and scripted test requests, captured on 2026-09-24.
  • This documentation uses system fonts only and loads no external files.
  • Trademarks (WordPress, OpenAI, ChatGPT, Anthropic, Claude, Google, Gemini, Microsoft, Copilot, Perplexity, Cloudflare, Coinbase and others) belong to their owners. Naming a company or bot does not imply endorsement.

32.Support policy

Support is provided through the Support tab on the CryptoMeter item page on CodeCanyon, following Envato's item support policy.

CoveredNot covered
  • Questions about the plugin's features and settings
  • Bugs in the plugin
  • Help with the setup described in this documentation
  • Custom development and custom hook code
  • Conflicts with third-party plugins or themes (beyond diagnosis)
  • Server, hosting, CDN, firewall or page-cache configuration
  • Facilitator accounts, Coinbase CDP accounts, wallets and on-chain issues
  • Legal or tax questions

Before you ask, please include

  • Your WordPress and PHP versions and the rows from Settings → Tools & status → System status
  • What the Activity log and the loopback test show for the request in question
  • The status of the lists on Bots & rules → Verification sources
  • Which cache, CDN or security plugins you use

Never send a private key, seed phrase, CDP key secret, webhook secret or WordPress password in a support request. We will never ask for them.