{"id":384051,"date":"2026-10-11T17:33:48","date_gmt":"2026-10-11T17:33:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/redkirin-ad-bot-click-guard\/"},"modified":"2026-10-15T06:04:00","modified_gmt":"2026-10-15T06:04:00","slug":"redkirin-ad-click-verification","status":"publish","type":"plugin","link":"https:\/\/kn.wordpress.org\/plugins\/redkirin-ad-click-verification\/","author":23583486,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.9.4","stable_tag":"1.9.4","tested":"7.1.3","requires":"5.8","requires_php":"7.4","requires_plugins":null,"header_name":"Redkirin Ad Click Verification","header_author":"Redkirin","header_description":"Stops bots from inflating GA4 events and Google Ads conversions by verifying that clicks on phone, LINE, email and other tracked links come from a real person.","assets_banners_color":"dc370b","last_updated":"2026-10-15 06:04:00","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/redkirin.co.jp\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":347,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.4":{"tag":"1.0.4","author":"redkirin","date":"2026-10-11 17:33:31","revision":3739880},"1.0.5":{"tag":"1.0.5","author":"redkirin","date":"2026-10-12 00:09:14","revision":3740287},"1.0.6":{"tag":"1.0.6","author":"redkirin","date":"2026-10-12 00:17:35","revision":3740290},"1.0.7":{"tag":"1.0.7","author":"redkirin","date":"2026-10-12 00:23:31","revision":3740293},"1.0.8":{"tag":"1.0.8","author":"redkirin","date":"2026-10-12 02:42:15","revision":3740380},"1.0.9":{"tag":"1.0.9","author":"redkirin","date":"2026-10-13 07:52:03","revision":3743203},"1.1.0":{"tag":"1.1.0","author":"redkirin","date":"2026-10-13 08:15:19","revision":3743244},"1.1.1":{"tag":"1.1.1","author":"redkirin","date":"2026-10-13 08:27:41","revision":3743265},"1.1.2":{"tag":"1.1.2","author":"redkirin","date":"2026-10-13 08:39:27","revision":3743276},"1.1.3":{"tag":"1.1.3","author":"redkirin","date":"2026-10-13 08:42:28","revision":3743290},"1.2.0":{"tag":"1.2.0","author":"redkirin","date":"2026-10-13 08:56:38","revision":3743325},"1.3.0":{"tag":"1.3.0","author":"redkirin","date":"2026-10-13 09:15:13","revision":3743355},"1.3.1":{"tag":"1.3.1","author":"redkirin","date":"2026-10-14 00:59:49","revision":3745123},"1.3.2":{"tag":"1.3.2","author":"redkirin","date":"2026-10-14 04:30:05","revision":3745269},"1.3.3":{"tag":"1.3.3","author":"redkirin","date":"2026-10-14 04:33:49","revision":3745274},"1.4.0":{"tag":"1.4.0","author":"redkirin","date":"2026-10-14 04:49:27","revision":3745308},"1.4.1":{"tag":"1.4.1","author":"redkirin","date":"2026-10-14 04:55:04","revision":3745321},"1.5.0":{"tag":"1.5.0","author":"redkirin","date":"2026-10-14 05:35:49","revision":3745392},"1.5.1":{"tag":"1.5.1","author":"redkirin","date":"2026-10-14 05:48:06","revision":3745408},"1.6.0":{"tag":"1.6.0","author":"redkirin","date":"2026-10-14 06:12:49","revision":3745440},"1.6.1":{"tag":"1.6.1","author":"redkirin","date":"2026-10-14 07:32:37","revision":3745566},"1.6.2":{"tag":"1.6.2","author":"redkirin","date":"2026-10-14 07:33:22","revision":3745568},"1.6.3":{"tag":"1.6.3","author":"redkirin","date":"2026-10-14 07:37:58","revision":3745578},"1.7.0":{"tag":"1.7.0","author":"redkirin","date":"2026-10-14 08:12:40","revision":3745666},"1.7.1":{"tag":"1.7.1","author":"redkirin","date":"2026-10-14 09:53:15","revision":3745917},"1.8.0":{"tag":"1.8.0","author":"redkirin","date":"2026-10-14 10:16:31","revision":3745975},"1.8.1":{"tag":"1.8.1","author":"redkirin","date":"2026-10-14 10:19:34","revision":3745987},"1.8.2":{"tag":"1.8.2","author":"redkirin","date":"2026-10-14 10:27:50","revision":3746013},"1.8.3":{"tag":"1.8.3","author":"redkirin","date":"2026-10-14 10:34:23","revision":3746036},"1.8.4":{"tag":"1.8.4","author":"redkirin","date":"2026-10-14 10:36:53","revision":3746041},"1.8.5":{"tag":"1.8.5","author":"redkirin","date":"2026-10-14 11:32:06","revision":3746190},"1.9.0":{"tag":"1.9.0","author":"redkirin","date":"2026-10-14 11:40:48","revision":3746217},"1.9.1":{"tag":"1.9.1","author":"redkirin","date":"2026-10-14 11:51:38","revision":3746235},"1.9.2":{"tag":"1.9.2","author":"redkirin","date":"2026-10-15 00:04:09","revision":3747353},"1.9.3":{"tag":"1.9.3","author":"redkirin","date":"2026-10-15 00:22:10","revision":3747377},"1.9.4":{"tag":"1.9.4","author":"redkirin","date":"2026-10-15 06:04:00","revision":3747684}},"upgrade_notice":{"1.0.2":"<p>Plugin folder and option names changed. Deactivate and delete the old &quot;Ad Click Verification&quot; before installing; settings are reset to defaults.<\/p>","1.0.1":"<p>Required update: 1.0.0 broke dataLayer pushes after Google Tag Manager loaded on real sites.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3745328,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3745328,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3745328,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3745328,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3745328,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.3.0","1.3.1","1.3.2","1.3.3","1.4.0","1.4.1","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.7.0","1.7.1","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.8.5","1.9.0","1.9.1","1.9.2","1.9.3","1.9.4"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[262246],"plugin_tags":[149009,286883,2359,984,985],"plugin_category":[55],"plugin_contributors":[285877],"plugin_business_model":[],"class_list":["post-384051","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-ad-fraud","plugin_tags-286883","plugin_tags-bot","plugin_tags-conversion","plugin_tags-google-ads","plugin_category-seo-and-marketing","plugin_contributors-redkirin","plugin_committers-redkirin"],"banners":{"banner":"https:\/\/ps.w.org\/redkirin-ad-click-verification\/assets\/banner-772x250.png?rev=3745328","banner_2x":"https:\/\/ps.w.org\/redkirin-ad-click-verification\/assets\/banner-1544x500.png?rev=3745328","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/redkirin-ad-click-verification\/assets\/icon.svg?rev=3745328","icon":"https:\/\/ps.w.org\/redkirin-ad-click-verification\/assets\/icon.svg?rev=3745328","icon_2x":false,"generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>\u65e5\u672c\u8a9e: \u96fb\u8a71\u30fbLINE\u30fb\u30e1\u30fc\u30eb\u306e\u30af\u30ea\u30c3\u30af\u3001\u30d5\u30a9\u30fc\u30e0\u9001\u4fe1\u3001\u5e83\u544a\u7740\u5730\u3092 bot \u306e\u4e0d\u6b63\u30af\u30ea\u30c3\u30af\u304b\u3089\u5b88\u308b\u30a2\u30c9\u30d5\u30e9\u30a6\u30c9\u5bfe\u7b56\u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u3059\u3002\u7ba1\u7406\u753b\u9762\u306f\u65e5\u672c\u8a9e\u306b\u5bfe\u5fdc\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n<p>Headless browsers and ad-platform crawlers execute JavaScript and click links. When a site measures phone (<code>tel:<\/code>), LINE, email or other link clicks as GA4 events or Google Ads conversions (for example through a Google Tag Manager \"Just Links\" trigger), those automated clicks are counted as conversions. GA4's built-in bot filtering is based on known bot lists and does not catch them.<\/p>\n\n<p>Redkirin Ad Click Verification is a lightweight ad fraud countermeasure focused on conversion integrity. It verifies that a click comes from a real person before it reaches your tags:<\/p>\n\n<ul>\n<li><strong>Human signals<\/strong> \u2013 records mouse movement, scrolling, touch and keyboard activity plus time on page from the moment the page starts loading. A long stay on the page (default 5 s) counts as one signal, so a visitor who reads and then taps a fixed call button is measured while instant taps are not.<\/li>\n<li><strong>Bot signals<\/strong> \u2013 <code>navigator.webdriver<\/code>, headless \/ crawler user agents (editable regex list), automation tool globals, missing language settings, and Google's published crawler IP ranges.<\/li>\n<li><strong>Click interception<\/strong> \u2013 unverified clicks are stopped at the <code>window<\/code> capture phase, before Google Tag Manager click triggers or inline <code>onclick<\/code> handlers see them. The navigation itself (dialing, opening LINE, following the link) is performed by the plugin, so visitors are never blocked.<\/li>\n<li><strong>dataLayer guard<\/strong> \u2013 <code>gtm.linkClick<\/code> \/ <code>gtm.click<\/code> and any event names you specify are dropped from <code>dataLayer.push<\/code> while the visitor is unverified.<\/li>\n<li><strong>Form submission verification<\/strong> \u2013 the same human verification applies to form submissions. Hidden fields carry the verdict for your CRM, verified submissions push <code>rkacv_form_submit<\/code>, submissions with definite bot signals are stopped (Contact Form 7 marks them as spam, WPForms rejects them), and thank-you pages only count when a verified form was submitted in the same session.<\/li>\n<li><strong>In-app browser detection<\/strong> \u2013 landings are classified by app (Yahoo! JAPAN, LINE, Facebook, Instagram, X, Google app, TikTok, generic WebView, ...), so you can see which apps bot traffic comes from even without ValueTrack placements.<\/li>\n<li><strong>Wasted spend estimate<\/strong> \u2013 enter an average CPC (or per campaign) and the report shows bot landings x CPC per campaign and in total.<\/li>\n<li><strong>Evidence export<\/strong> \u2013 CSV of bot landings and blocked clicks for the Google Ads invalid click claim form.<\/li>\n<li><strong>Alerts<\/strong> \u2013 hourly check with email when the bot share of ad landings or repeated conversions from one click ID exceed your thresholds; optional daily digest.<\/li>\n<li><strong>Country restriction<\/strong> \u2013 allow-list or block-list of countries (all ISO countries, grouped by region, searchable). Measurement of phone \/ LINE \/ form clicks and verified events is withheld for restricted countries, optionally with an HTTP 403. The country comes from the Internet registries (RDAP) or a CDN country header, not from a third-party geolocation API; unknown countries are measured by default.<\/li>\n<li><strong>Page view protection<\/strong> \u2013 obvious bots (webdriver, bot user agents, automation globals) get no tags at all: every dataLayer push is dropped, so GTM and gtag.js send nothing, not even page_view. Once a visitor is verified, a <code>rkacv_verified_pageview<\/code> event is pushed that you can use as a key event instead of page_view (thank-you pages, landing pages).<\/li>\n<li><strong>Verified events<\/strong> \u2013 verified clicks push <code>rkacv_verified_click<\/code> to the dataLayer (with <code>rkacv_link_type<\/code>, <code>rkacv_link_url<\/code>, <code>rkacv_link_text<\/code>, <code>rkacv_element_id<\/code>), and can optionally call <code>gtag('event', ...)<\/code> directly.<\/li>\n<li><strong>Scope<\/strong> \u2013 protect only matched links (phone \/ LINE \/ email by default), every link, or every click including buttons.<\/li>\n<li><strong>Deny page access to bots (optional, off by default)<\/strong> \u2013 return HTTP 403 to IP ranges you registered and to headless browsers, automation tools and HTTP libraries. Search engine and ad review crawlers are never blocked. Optionally hide the page in the browser when <code>navigator.webdriver<\/code> is detected.<\/li>\n<li><strong>Repeat conversion suppression<\/strong> \u2013 one ad click (one gclid) can only produce a verified phone \/ LINE click once per link type within a window (default 30 minutes) and at most a daily limit per click ID (default 3) across tabs, devices and reloads. Stops manual or automated \"conversion seeding\" from a single paid click.<\/li>\n<li><strong>Every ad platform<\/strong> \u2013 click IDs from Google (gclid \/ gbraid \/ wbraid), Meta (fbclid), Yahoo! JAPAN (yclid), LINE (ldtag_cl), TikTok (ttclid), X (twclid) and Microsoft (msclkid) are recognised for ad landings and repeat suppression; the report breaks landings down by platform. A directly installed Meta Pixel or Yahoo tag is never loaded for obvious bots, and verified events can be sent to the Meta Pixel as custom events.<\/li>\n<li><strong>Ad traffic analysis<\/strong> \u2013 every visit arriving with an ad click parameter (gclid, gbraid, wbraid, ...) is scored human \/ undetermined \/ bot and recorded with its campaign, placement and device (Google Ads ValueTrack parameters are read from the URL). The \"Ad traffic\" report shows the bot share per campaign and placement, repeat landings from the same IP or click ID, verified clicks per campaign, and an exportable list of IP ranges for Google Ads IP exclusions.<\/li>\n<li><strong>Dashboard widget<\/strong> \u2013 7-day ad traffic (landings, bot share, undetermined, human, estimated waste, daily chart, top campaigns) and click summary with a daily chart, top block reasons and the latest blocked clicks.<\/li>\n<li><strong>Log<\/strong> \u2013 blocked and verified clicks are logged with the reason, so you can tune thresholds. IP addresses are anonymised by default. The log endpoint only accepts requests carrying a token signed by the site, is rate limited per IP and site-wide, and the table is capped and purged automatically.<\/li>\n<\/ul>\n\n<p>Works with page caching plugins: nothing visitor-specific is embedded in the HTML. Server-side IP checks run through the REST API.<\/p>\n\n<p>The admin UI is in English with a bundled Japanese translation (the plugin targets LINE-based lead generation common in Japan).<\/p>\n\n<p>Google Analytics, Google Ads and Google Tag Manager are trademarks of Google LLC. LINE is a trademark of LY Corporation. This plugin is an independent product of Redkirin and is not affiliated with or endorsed by Google or LY Corporation; the names are used only to describe compatibility.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin can connect to three external services.<\/p>\n\n<p><strong>RDAP (network operator lookup)<\/strong> \u2013 When \"Show the network operator next to IP addresses\" is enabled (default: enabled), the plugin asks the public RDAP services of the Internet registries who the registered owner of an anonymised IP range is (mobile carrier, ISP, hosting provider, or the company holding a fixed-IP assignment) and caches the answer for 30 days. Japanese ranges are looked up at JPNIC (https:\/\/rdap.nic.ad.jp\/ip\/{range}, terms: https:\/\/www.nic.ad.jp\/en\/db\/whois\/), other ranges through https:\/\/rdap.org\/ip\/{range}, which forwards to the responsible regional registry. Only the anonymised \/24 range (last octet zero) is sent, never a full visitor IP, and lookups happen on the server from WP-Cron or when an administrator opens the log. Service: https:\/\/about.rdap.org\/ \u2013 registry terms: https:\/\/www.apnic.net\/about-apnic\/corporate-documents\/documents\/resource-management\/apnic-whois-terms-and-conditions\/<\/p>\n\n<p><strong>Google crawler IP ranges<\/strong> \u2013 When the \"Google crawler IP check\" option is enabled (default: enabled), the plugin downloads Google's published crawler IP range lists once a day via WP-Cron, on plugin activation, and when an administrator clicks \"Refresh\" on the Log screen. The lists are cached in a transient. Only the server makes this request; no visitor data is sent to Google by the plugin.<\/p>\n\n<ul>\n<li>https:\/\/developers.google.com\/static\/search\/apis\/ipranges\/googlebot.json<\/li>\n<li>https:\/\/developers.google.com\/static\/search\/apis\/ipranges\/special-crawlers.json<\/li>\n<li>https:\/\/developers.google.com\/static\/search\/apis\/ipranges\/user-triggered-fetchers-google.json<\/li>\n<\/ul>\n\n<p>Published by Google: https:\/\/developers.google.com\/search\/docs\/crawling-indexing\/verifying-googlebot<\/p>\n\n<p><strong>Cloudflare IP ranges<\/strong> \u2013 Only when \"Cloudflare mode\" is enabled (default: off; the plugin offers it when it detects that the site is served through Cloudflare without the real visitor IP being restored), the plugin downloads Cloudflare's published IP range list once a day from https:\/\/www.cloudflare.com\/ips-v4\/ and https:\/\/www.cloudflare.com\/ips-v6\/ and caches it for two days. No visitor data is sent; the list is used to verify that a request really comes from Cloudflare before the CF-Connecting-IP header is accepted as the visitor IP. Published by Cloudflare: https:\/\/www.cloudflare.com\/ips\/\nGoogle terms of service: https:\/\/policies.google.com\/terms \u2013 Privacy policy: https:\/\/policies.google.com\/privacy<\/p>\n\n<p>The plugin does not send anything to Google Analytics or Google Ads by itself; it only decides whether the tags you have already installed receive a click.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>redkirin-ad-click-verification<\/code> folder to <code>\/wp-content\/plugins\/<\/code> or install the zip from Plugins \u2192 Add New.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Open the new \"Ad Click Verification\" menu in the admin sidebar. The defaults work for phone \/ LINE \/ email links with an existing Google Tag Manager setup.<\/li>\n<li>Optionally create a GTM custom event trigger for <code>rkacv_verified_click<\/code> and move your conversion tags to it (see the guide tab in the settings screen).<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20it%20block%20visitors%3F\"><h3>Does it block visitors?<\/h3><\/dt>\n<dd><p>No. Only the measurement is withheld. Phone calls, LINE and other links always work; when a click is intercepted the plugin performs the navigation itself.<\/p><\/dd>\n<dt id=\"do%20i%20have%20to%20change%20my%20google%20tag%20manager%20container%3F\"><h3>Do I have to change my Google Tag Manager container?<\/h3><\/dt>\n<dd><p>Not necessarily. With \"Intercept unverified clicks\" enabled, existing \"Click \u2013 Just Links\" triggers simply stop firing for bots. For the cleanest setup, create a custom event trigger for <code>rkacv_verified_click<\/code> and pause your old click triggers to avoid double counting.<\/p><\/dd>\n<dt id=\"what%20about%20visitors%20who%20tap%20a%20phone%20number%20immediately%20after%20the%20page%20loads%3F\"><h3>What about visitors who tap a phone number immediately after the page loads?<\/h3><\/dt>\n<dd><p>A tap within the minimum dwell time (default 1 second) with no prior interaction cannot be distinguished from a bot and is not measured. Lower the dwell time or set the required signal count to 0 if this matters more than bot filtering.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20caching%20plugins%20and%20cdns%3F\"><h3>Does it work with caching plugins and CDNs?<\/h3><\/dt>\n<dd><p>Yes. All verification happens in the browser and via the REST API. Behind a reverse proxy or CDN, return the real visitor IP with the <code>rkacv_client_ip<\/code> filter so the IP range check works.<\/p><\/dd>\n<dt id=\"what%20data%20is%20stored%3F\"><h3>What data is stored?<\/h3><\/dt>\n<dd><p>An optional log of blocked \/ verified clicks: time, link URL, page URL, reason, dwell time, signal count, user agent and an anonymised IP (last octet \/ lower 80 bits zeroed; can be disabled). Logs are purged after the configured number of days and the table keeps the newest 20,000 rows. Everything is removed on uninstall.<\/p><\/dd>\n<dt id=\"can%20page%20view%20based%20key%20events%20%28thank-you%20pages%29%20be%20protected%20too%3F\"><h3>Can page view based key events (thank-you pages) be protected too?<\/h3><\/dt>\n<dd><p>Yes. Obvious bots get no tags at all (\"Fire no tags for obvious bots\"), and once a visitor is verified the plugin pushes rkacv_verified_pageview. Use that event, optionally with a page path condition, as your key event instead of page_view. Bots that are only recognisable after the page view was sent (IP range, no interaction) cannot be removed from page_view itself, which is why the verified event exists.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20meta%20ads%2C%20yahoo%21%20japan%20ads%20or%20other%20platforms%3F\"><h3>Does it work with Meta Ads, Yahoo! JAPAN Ads or other platforms?<\/h3><\/dt>\n<dd><p>Yes. Verification acts on the page, so it is platform-independent. Click IDs from Google, Meta (fbclid), Yahoo! JAPAN (yclid), LINE, TikTok, X and Microsoft are recognised for landings and repeat suppression, and the report shows a per-platform breakdown. Fire each platform's conversion tag from GTM on the verified events (rkacv_verified_click, rkacv_form_submit, rkacv_verified_pageview); a directly installed Meta Pixel can receive the verified events as custom events.<\/p><\/dd>\n<dt id=\"does%20the%20ad%20traffic%20report%20tell%20me%20which%20placements%20to%20exclude%3F\"><h3>Does the ad traffic report tell me which placements to exclude?<\/h3><\/dt>\n<dd><p>It shows, per campaign and per placement, how many landings carried definite bot signals (webdriver, synthetic clicks, headless user agents, crawler IPs) versus how many looked human. Placement and device breakdowns require Google Ads ValueTrack parameters in your tracking template, for example <code>{lpurl}?campaignid={campaignid}&amp;placement={placement}&amp;device={device}<\/code>. The plugin never changes your Google Ads account; exclusions are applied by you in Google Ads.<\/p><\/dd>\n<dt id=\"can%20the%20log%20be%20trusted%3F\"><h3>Can the log be trusted?<\/h3><\/dt>\n<dd><p>The log is diagnostic data reported by visitors' browsers. The endpoint requires a token signed by the site, but the token is part of the public page, so anyone who can load the page can also post entries. Treat the log as a tuning aid, not as evidence: it never changes what GA4 or Google Ads measure. Writes are rate limited per IP and site-wide, capped per IP per day, and when the table is full the oldest rows are discarded so new entries are always stored.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.9.4<\/h4>\n\n<ul>\n<li>Directory listing: Japanese keyword \"\u30a2\u30c9\u30d5\u30e9\u30a6\u30c9\" added to the tags, the short description and the description so the plugin can be found by Japanese searches.<\/li>\n<\/ul>\n\n<h4>1.9.3<\/h4>\n\n<ul>\n<li>Japanese translation: three remaining spacing fixes.<\/li>\n<\/ul>\n\n<h4>1.9.2<\/h4>\n\n<ul>\n<li>Japanese translation brought in line with the WordPress Japanese style guide (half-width parentheses with outer spaces, \u3059\u3067\u306b \/ \u3059\u3079\u3066 \/ \u304f\u3060\u3055\u3044, \u306a\u3069, no spaces around counts).<\/li>\n<\/ul>\n\n<h4>1.9.1<\/h4>\n\n<ul>\n<li>The first option on the Basic settings tab is now called \"Protect the site (master switch)\" and explains what it pauses; the deny-page feature now also respects it.<\/li>\n<\/ul>\n\n<h4>1.9.0<\/h4>\n\n<ul>\n<li>Cloudflare detection and Cloudflare mode. When an administrator opens a plugin screen through Cloudflare and the server has not restored the real visitor IP, a warning explains that IP checks, country restriction and the logs are seeing Cloudflare addresses, with a one-click \"Enable Cloudflare mode\" button. In Cloudflare mode the plugin downloads Cloudflare's IP ranges daily and, only for requests that really come from those ranges, uses CF-Connecting-IP as the visitor IP and trusts the CF-IPCountry country header. A generic reverse-proxy warning (private REMOTE_ADDR with X-Forwarded-For) points to the rkacv_client_ip filter. The current request's status is shown next to the new \"Reverse proxy \/ CDN\" setting.<\/li>\n<\/ul>\n\n<h4>1.8.5<\/h4>\n\n<ul>\n<li>Security hardening: the CDN country header (CF-IPCountry \/ CloudFront-Viewer-Country) is no longer trusted by default, because on a site that is not behind such a CDN anyone could forge it to bypass the country restriction; a new \"Trust the CDN country header\" option on the Country restriction tab enables it. Synchronous registry lookups triggered from the public check endpoint are capped site-wide (30 per minute, filter rkacv_geo_sync_lookups_per_minute). Evidence CSV cells that start with =, +, -, @ or a tab are quoted so spreadsheets do not execute them.<\/li>\n<li>The page cache warning stays hidden for 12 hours for the administrator who clicked \"Clear page cache now\".<\/li>\n<\/ul>\n\n<h4>1.8.4<\/h4>\n\n<ul>\n<li>Dashboard widget is titled \"Redkirin Ad Click Verification\".<\/li>\n<\/ul>\n\n<h4>1.8.3<\/h4>\n\n<ul>\n<li>Number fields on the settings tabs (average CPC, dwell times, delays, retention days, thresholds) are wide enough to show six digits; text fields and textareas no longer overflow their column.<\/li>\n<\/ul>\n\n<h4>1.8.2<\/h4>\n\n<ul>\n<li>Wasted spend estimate is no longer hidden while the average CPC is unset: the Ad traffic report, the dashboard widget and the daily digest show \"Average CPC not set\" with a clearly labelled example calculation and a link to the setting. The CPC field explains where to copy the figure from.<\/li>\n<li>Network operator \/ company names next to IP addresses are shown in full instead of being cut off with an ellipsis.<\/li>\n<\/ul>\n\n<h4>1.8.1<\/h4>\n\n<ul>\n<li>New \"Ad fraud\" settings tab: ad traffic analysis, wasted spend estimate, alerts and scripted repetition detection moved there from Advanced settings, each tab with its own reset button.<\/li>\n<\/ul>\n\n<h4>1.8.0<\/h4>\n\n<ul>\n<li>Scripted repetition detection: groups of different IPs that repeat the same sequence of clicks \/ form submissions on the same pages with the same browser and almost identical timing are listed on the Event log tab (\"Scripted\" badge on their rows, one-click \"Add bot IP\") and reported by the alert email. Catches stealth bots that hide the webdriver flag and pass the dwell \/ interaction checks.<\/li>\n<li>Hosting providers such as Contabo, IONOS, Scaleway, Leaseweb, M247 and Hostinger (plus many more VPS \/ cloud names and Japanese hosts) are now labelled as hosting and shown in red; registry names containing \"host\", \"server\", \"cloud\", \"datacenter\", \"vps\" or \"colo\" are flagged too.<\/li>\n<li>Country restriction moved to its own tab with its own \"Reset this tab\" button.<\/li>\n<\/ul>\n\n<h4>1.7.1<\/h4>\n\n<ul>\n<li>Country is now stored with every click log entry and ad landing (DB version 7) and shown as a badge next to every IP, Japan included. The event log gets a \"By country (7 days)\" strip with per-country filtering and an \"Exclude  from measurement\" shortcut that pre-selects the country in the block list. Known countries are back-filled into older rows as lookups complete.<\/li>\n<li>Every reason in the event log and ad landing tables now has an (i) icon; hover or click it for a plain-language explanation of what was detected.<\/li>\n<\/ul>\n\n<h4>1.7.0<\/h4>\n\n<ul>\n<li>New \"Country restriction\" (Advanced settings): allow-list or block-list of countries with a searchable, region-grouped checkbox grid, \"countries seen recently\", fail-open for unknown countries, optional HTTP 403, and a \"By country\" breakdown in the Ad traffic report. Uses the registry country from the RDAP lookups or a CDN header (Cloudflare, CloudFront); no geolocation API.<\/li>\n<\/ul>\n\n<h4>1.6.3<\/h4>\n\n<ul>\n<li>Ad traffic: every breakdown table now has the same columns. Verified clicks (matched by click ID) and the estimated waste are computed per platform, campaign, app, placement, device and source, so the bot-share bars line up across tables.<\/li>\n<\/ul>\n\n<h4>1.6.2<\/h4>\n\n<ul>\n<li>The admin sidebar menu is now labelled \"Redkirin Ad Click Verification\".<\/li>\n<\/ul>\n\n<h4>1.6.1<\/h4>\n\n<ul>\n<li>Layout: report headers no longer wrap, breakdown tables with no data for their dimension are hidden, numeric gad_source values are labelled, the event log uses proportional column widths and the network operator badge sits under the IP instead of overflowing.<\/li>\n<li>The \"Log\" tab and menu are now called \"Event log\".<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li>Log and Ad traffic: the network operator (NTT docomo, au, SoftBank, Rakuten Mobile, ISPs, cloud \/ hosting providers, or the company holding a fixed-IP assignment registered with JPNIC) and the country are shown next to each anonymised IP, looked up through the public RDAP services of JPNIC and the regional registries and cached for 30 days.<\/li>\n<li>Settings: \"Reset this tab to defaults\" button on the Basic and Advanced settings tabs. Hosting \/ cloud ranges and ranges registered outside Japan are highlighted; the country code is included in the evidence CSV. Lookups run hourly via WP-Cron, a few at a time when the log is opened, or on demand with \"Look up network operators\". New option under Bot detection; disclosed under External services.<\/li>\n<\/ul>\n\n<h4>1.5.1<\/h4>\n\n<ul>\n<li>The plugin script is excluded automatically from JavaScript optimisation (aggregation, defer, delayed execution) in Autoptimize, WP Rocket, LiteSpeed Cache, Perfmatters, Flying Press, SiteGround Optimizer and WP-Optimize, and any defer \/ async attribute is removed, so it keeps running in the head before Google Tag Manager. Without this, deferred execution delayed the bot tag block and could lose early landings.<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>Dashboard widget: new ad traffic section with landings, bot share, undetermined, human, estimated waste, a daily chart by verdict and the top campaigns.<\/li>\n<li>Ad landings are now recorded in two steps: a provisional record right after the minimum dwell time and a final verdict after the delay or on leave. Visits from in-app browsers that are closed without a leave event are no longer lost. The final update is authenticated with a per-row signed key.<\/li>\n<\/ul>\n\n<h4>1.4.1<\/h4>\n\n<ul>\n<li>Log: the \"Add bot IP\" button is shown only for rows with definite bot signals, not for repeat or undetermined rows that may be real visitors.<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Meta, Yahoo! JAPAN, LINE, TikTok, X and Microsoft click IDs (fbclid, yclid, ldtag_cl, ttclid, twclid, msclkid) are recognised for ad landings and repeat suppression; new \"By platform\" breakdown and platform column \/ CSV field.<\/li>\n<li>Directly installed Meta Pixel (fbq) and Yahoo tag (ytag \/ yjDataLayer) are disabled for obvious bots together with GTM \/ gtag.<\/li>\n<li>Optional \"Send verified events to the Meta Pixel\" (VerifiedClick \/ VerifiedPageView \/ VerifiedFormSubmit custom events).<\/li>\n<li>Default trigger \/ capture parameters extended (campaign_id, adset_id, ad_id, site_source_name, utm_term); existing installations get the new names appended automatically.<\/li>\n<li>Guide section for Meta Ads, Yahoo! JAPAN Ads and other platforms.<\/li>\n<\/ul>\n\n<h4>1.3.3<\/h4>\n\n<ul>\n<li>Cache plugin awareness: detects common page cache plugins, shows a notice with a \"Clear page cache now\" button on the plugin screens, and clears the cache automatically after plugin updates and settings saves (filter <code>rkacv_cache_plugins<\/code> to add others).<\/li>\n<\/ul>\n\n<h4>1.3.2<\/h4>\n\n<ul>\n<li>Log screen: \"Repeat\" filter and a \"Repeat blocked, last 7 days\" card so suppressed repeat conversions are easy to find.<\/li>\n<\/ul>\n\n<h4>1.3.1<\/h4>\n\n<ul>\n<li>The plugin now has its own top-level admin menu (Basic settings, Advanced settings, Log, Ad traffic, Guide) instead of living under Settings; old links redirect.<\/li>\n<li>Ad traffic report: consistent column widths across the breakdown tables and equal-width summary cards.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>In-app browser classification for ad landings (new \"By app\" breakdown and column); evidence CSV export for Google Ads invalid click claims; wasted spend estimate (bot landings x CPC, per campaign CPC overrides) in the report, the dashboard and the digest.<\/li>\n<li>Form submission verification: hidden verdict fields, rkacv_form_submit event for verified submissions, blocking of submissions with definite bot signals (browser, Contact Form 7 spam, WPForms error), configurable excluded forms.<\/li>\n<li>Thank-you page gating: verified page view \/ rkacv_thanks_view only after a verified form submission in the same session; direct hits are logged.<\/li>\n<li>Alert emails (hourly check: bot share, repeated conversions per click ID) and an optional daily digest.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>New \"Fire no tags for obvious bots\" (default on): when webdriver, a bot user agent or automation globals are present at load, every dataLayer push is dropped so GTM \/ gtag.js send nothing, including page_view.<\/li>\n<li>New \"Send a verified page view event\" (default on): pushes rkacv_verified_pageview (and verified_page_view via gtag when direct sending is enabled) once the visitor is verified. Use it as a key event instead of page_view.<\/li>\n<li>Guide: new section on page view based key events.<\/li>\n<\/ul>\n\n<h4>1.1.3<\/h4>\n\n<ul>\n<li>Settings are split into \"Basic settings\" (scope, thresholds, blocking, verified events, repeat suppression, log) and \"Advanced settings\" (bot detection, ad traffic analysis, deny page access). Saving one tab keeps the values of the other.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<ul>\n<li>Settings: options that depend on a master switch (deny page access, repeat suppression, ad landings, logging, dataLayer guard) are greyed out and not editable until the switch is on. Values are preserved.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>New \"Repeat conversion suppression\": verified phone \/ LINE clicks are measured once per link type per click ID (or per browser session) within a window, and at most a daily limit per click ID checked against the log through the REST API. Repeats are intercepted and logged with the reason \"Repeat\".<\/li>\n<li>The log stores the click ID (gclid \/ gbraid \/ wbraid \/ msclkid \/ yclid) of each entry; the Ad traffic report lists click IDs with repeated conversions (verified, repeat-blocked, distinct IPs, first \/ last time).<\/li>\n<li>Keyboard activity on a touch device is recorded as a note in the log (a hint of desktop device emulation or automation); it does not change the verdict.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>New \"Ad traffic\" report: ad landings (gclid \/ gbraid \/ wbraid \/ gad_campaignid and ValueTrack parameters) are scored human \/ undetermined \/ bot after a configurable delay or on leave, and broken down by campaign, placement, device and source with the bot share, repeat landings (same IP within 10 minutes, same click ID within 24 hours), verified clicks matched by click ID, and an exportable list of IP ranges for Google Ads IP exclusions.<\/li>\n<li>New settings section \"Ad traffic analysis\" (recording on by default when logging is on; trigger \/ capture parameters, verdict delay, retention).<\/li>\n<li>Dashboard widget shows the ad landing count and bot share.<\/li>\n<li>New table <code>rkacv_ad_visits<\/code> with the same protections as the log (signed token, rate limits, per-IP daily cap, ring buffer, retention).<\/li>\n<\/ul>\n\n<h4>1.0.9<\/h4>\n\n<ul>\n<li>Log table is now a ring buffer: when the 20,000-row cap is reached the oldest rows are discarded instead of refusing new entries, so flooding cannot suppress new logs.<\/li>\n<li>New per-IP daily cap on log rows (default 300, filter <code>rkacv_log_ip_daily_limit<\/code>).<\/li>\n<li>Clarified in the settings and readme that the log is untrusted diagnostic data.<\/li>\n<\/ul>\n\n<h4>1.0.8<\/h4>\n\n<ul>\n<li>New dashboard widget: blocked \/ bot-signal \/ undetermined \/ verified \/ denied counts for the last 7 days, a daily bar chart, top block reasons and the latest blocked clicks.<\/li>\n<\/ul>\n\n<h4>1.0.7<\/h4>\n\n<ul>\n<li>New optional \"Deny page access to bots\" section: HTTP 403 for registered bot IP ranges and automation \/ HTTP-library user agents, with a protected list of search engine and ad crawlers that are never denied. Optional client-side hiding when navigator.webdriver is detected. Denied requests are logged with a new \"Denied\" status and filter.<\/li>\n<\/ul>\n\n<h4>1.0.6<\/h4>\n\n<ul>\n<li>Log screen: blocked rows are marked \"Bot signals\" (definite bot indicators) or \"Undetermined\" (dwell \/ interaction only) and colour-coded; IPs blocked more than once show a count.<\/li>\n<li>Log screen: new \"Bot signals\" filter.<\/li>\n<li>Log screen: one-click \"Add bot IP\" button adds the row's IP range (\/24 for anonymised IPv4, \/48 for IPv6) to the additional bot CIDR list, shown only when the user agent is not already matched by a bot pattern.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Admin UI source strings are now English; Japanese translation is bundled (languages\/) and loaded via load_plugin_textdomain.<\/li>\n<li>Reason labels in the log are now translatable.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>New \"dwell as signal\" threshold (default 5000 ms): a long stay counts as one interaction signal, so visitors who read without scrolling and then tap a fixed call\/LINE button are measured, while instant taps are still withheld.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Renamed to Redkirin Ad Click Verification (slug <code>redkirin-ad-click-verification<\/code>, prefix <code>rkacv_<\/code>). dataLayer keys are now <code>rkacv_verified_click<\/code>, <code>rkacv_human<\/code>, <code>rkacv_link_type<\/code>, etc.<\/li>\n<li>The log endpoint now requires a site-signed token (permission_callback) in addition to rate limits.<\/li>\n<li>Shortened the readme description; added trademark notice.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Renamed to Redkirin Ad Click Verification (slug <code>redkirin-ad-click-verification<\/code>, PHP prefix <code>rkacv_<\/code>). dataLayer keys (<code>rkacv_verified_click<\/code>, <code>rkacv_human<\/code>, <code>rkacv_link_type<\/code>, ...) are unchanged.<\/li>\n<li>Store log timestamps in UTC and display them in the site timezone.<\/li>\n<li>Cap the log table at 20,000 rows and add a site-wide rate limit for the log endpoint.<\/li>\n<li>Lock concurrent refreshes of the Google crawler IP range cache.<\/li>\n<li>Fix: saving settings removed backslashes from bot user-agent regular expressions.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fix: dataLayer guard caused infinite recursion with the real Google Tag Manager runtime, which wraps the original <code>dataLayer.push<\/code>. The guard now keeps a chain of replaced implementations and delegates on re-entry.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Ad fraud protection (\u30a2\u30c9\u30d5\u30e9\u30a6\u30c9\u5bfe\u7b56) for conversions: keeps bot clicks on phone, LINE, email and other tracked links out of GA4 events and Google Ads.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/384051","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=384051"}],"author":[{"embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/redkirin"}],"wp:attachment":[{"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=384051"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=384051"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=384051"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=384051"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=384051"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/kn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=384051"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}