Title: AlgoRadar
Author: Francesco Palmieri
Published: <strong>September 23, 2026</strong>
Last modified: September 24, 2026

---

Search plugins

![](https://ps.w.org/algoradar/assets/banner-772x250.png?rev=3710970)

![](https://ps.w.org/algoradar/assets/icon.svg?rev=3710970)

# AlgoRadar

 By [Francesco Palmieri](https://profiles.wordpress.org/ceotech/)

[Download](https://downloads.wordpress.org/plugin/algoradar.0.3.14.zip)

 * [Details](https://wordpress.org/plugins/algoradar/#description)
 * [Reviews](https://wordpress.org/plugins/algoradar/#reviews)
 *  [Installation](https://wordpress.org/plugins/algoradar/#installation)
 * [Development](https://wordpress.org/plugins/algoradar/#developers)

 [Support](https://wordpress.org/support/plugin/algoradar/)

## Description

AlgoRadar analyzes the content already published on your WordPress site and calculates
two indicative scores:

 * **Core Exposure Score** — exposure to content-quality factors typically involved
   in core updates (thin content, duplicates, weak internal linking, technical issues).
 * **Spam Exposure Score** — exposure to patterns typical of spam updates (risky
   outbound links, keyword stuffing, doorway pages).

Both scores come from a **local, configurable** heuristic model, never from Google’s
actual algorithm: AlgoRadar is not a Google product, does not replicate its inner
workings, and does not predict real penalties. Every factor that contributes to 
a score is shown transparently (data point, reason, weight, suggestion), so the 
score is never a number without an explanation.

#### Built to go easy on your hosting

Where possible, AlgoRadar reads data directly from the WordPress database (content,
internal links, metadata) instead of scanning the site over HTTP. Actual HTTP requests
are reserved only for the signals that genuinely need them, such as real response
time. The background scan uses WP-Cron with chained batch execution, with a browser-
driven fallback for hosting environments where background execution isn’t reliable.

#### No paid services

AlgoRadar works exclusively with data already present on your site and, if you connect
it, with the official, free Google Search Console API to compare scores against 
real clicks and impressions. No integration with paid SEO services.

### External services

AlgoRadar connects to one third-party service, and only if you explicitly turn it
on: the official **Google Search Console API**. It is off by default and every scoring
feature works without it.

**What it’s for**: on the Compare page, if you choose to connect your Google account,
AlgoRadar fetches your site’s real clicks and impressions per URL from Search Console
so you can see them alongside the plugin’s own Core/Spam Exposure Scores.

**What is sent, and when**:

 * Connecting: when you click “Connect” in AlgoRadar > Settings, your browser is
   redirected to Google’s OAuth consent screen (`https://accounts.google.com/o/oauth2/
   v2/auth`) to authorize read-only access to your Search Console data. No site 
   data is sent at this step, only the standard OAuth request.
 * Token exchange/refresh: after you authorize, the plugin exchanges the authorization
   code (and later, silently, the refresh token) for an access token by calling 
   Google’s token endpoint (`https://oauth2.googleapis.com/token`). This request
   includes the OAuth credentials you entered (Client ID/Secret) and the token/code
   itself; no content from your site is sent.
 * Fetching data: when you open the Compare page with a Search Console property 
   selected, the plugin calls the Search Console API (`https://www.googleapis.com/
   webmasters/v3`, read-only scope) to request clicks/impressions per URL for your
   own site’s property, for the date range being compared. This happens only on 
   that page load, only for a connected account, and never during the background
   scan itself.

No content, personal data of your visitors, or site data other than your own page
URLs and the date range being queried is ever sent to Google. You can disconnect
at any time from AlgoRadar > Settings, which deletes the stored tokens.

This integration is governed by Google’s own terms: [Google APIs Terms of Service](https://developers.google.com/terms/)
and [Google Privacy Policy](https://policies.google.com/privacy).

## Screenshots

[⌊Dashboard: Core and Spam Exposure Score at a glance, with a prioritized list of
pages to check first.⌉⌊Dashboard: Core and Spam Exposure Score at a glance, with
a prioritized list of pages to check first.⌉[

Dashboard: Core and Spam Exposure Score at a glance, with a prioritized list of 
pages to check first.

[⌊Page detail: every factor behind the score, with its data point, reason, weight,
and suggestion — never a number without an explanation.⌉⌊Page detail: every factor
behind the score, with its data point, reason, weight, and suggestion — never a 
number without an explanation.⌉[

Page detail: every factor behind the score, with its data point, reason, weight,
and suggestion — never a number without an explanation.

[⌊Pages: every analyzed URL with its scores and priority.⌉⌊Pages: every analyzed
URL with its scores and priority.⌉[

Pages: every analyzed URL with its scores and priority.

[⌊Compare: track scores between two scans over time, and correlate them with real
Search Console clicks and impressions.⌉⌊Compare: track scores between two scans 
over time, and correlate them with real Search Console clicks and impressions.⌉[

Compare: track scores between two scans over time, and correlate them with real 
Search Console clicks and impressions.

[⌊Settings: every weight and threshold is visible and adjustable, never a hidden
default.⌉⌊Settings: every weight and threshold is visible and adjustable, never 
a hidden default.⌉[

Settings: every weight and threshold is visible and adjustable, never a hidden default.

## Installation

 1. Upload the `algoradar` folder to `/wp-content/plugins/`, or install the zip via
    Plugins > Add New > Upload Plugin.
 2. Activate the plugin from the WordPress Plugins menu.
 3. Go to AlgoRadar > Settings to review the default values (no configuration is required
    to get started).
 4. Go to AlgoRadar > Dashboard for your site’s status.

## FAQ

### Are the scores official Google metrics?

No. They’re calculated by a local heuristic model included in the plugin, with weights
you can change yourself in Settings. They don’t come from internal Google documentation
and don’t guarantee or predict any action by Google on your site.

### Does the plugin send my data to external services?

No, by default. The only optional external connection is to the official Google 
Search Console API, which you can enable voluntarily from the Settings page, and
it’s used only to compare scores against real organic traffic data.

### Does it need a system cron?

No. AlgoRadar uses WP-Cron for background execution and, if your hosting doesn’t
run it reliably, falls back to browser-driven batch processing. If neither is reliable
enough on your host, `wp algoradar scan` (requires WP-CLI) runs a scan to completion
from a real system cron job, without depending on WP-Cron or a browser tab.

### How do I get support?

Write to info@ceotech.it for questions, bug reports, or requests.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“AlgoRadar” is open source software. The following people have contributed to this
plugin.

Contributors

 *   [ Francesco Palmieri ](https://profiles.wordpress.org/ceotech/)

[Translate “AlgoRadar” into your language.](https://translate.wordpress.org/projects/wp-plugins/algoradar)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/algoradar/), check 
out the [SVN repository](https://plugins.svn.wordpress.org/algoradar/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/algoradar/) by [RSS](https://plugins.trac.wordpress.org/log/algoradar/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 0.3.14

 * Fixed a fatal error on the “Storico scansioni” page introduced in 0.3.12: the
   file it needed (admin/views/storico.php) had not actually been added to version
   control, so it was missing from that release (and from the 0.3.13 tag, which 
   only corrected the file itself but not this readme’s Stable tag).

#### 0.3.12

 * Added a new “Storico scansioni” admin page listing every saved scan with an estimated
   data size, a full CSV export (every factor’s data and risk score, not just the
   top suggestion) and a per-scan delete button.
 * Added an option to permanently delete all scan history in one action, behind 
   an explicit confirmation checkbox.
 * Added an optional, off-by-default setting to automatically delete completed scans
   beyond the most recent N kept: existing installs keep every scan forever, exactly
   as before, unless this is turned on in Settings.

#### 0.3.11

 * Added two new Core Exposure Score factors, both free local checks on the page’s
   own real HTML, no paid service involved: Mobile Viewport (presence of the `<meta
   name="viewport">` tag) and Structured Data (presence of JSON-LD or microdata).
   Both are presence checks, not full validity checks, and neither can force Priority
   1 on its own.

#### 0.3.10

 * Fixed a false-positive risk in Keyword Stuffing on review-style content: the 
   factor now excludes words that already appear in the page’s own title before 
   counting repetitions, so a product or brand name repeated throughout a review(
   expected on this kind of content) is no longer counted as unnatural repetition.
 * Renamed the “Freshness/Authorship” factor to “Freshness”: it has only ever measured
   how long ago a page was last updated, with no authorship signal (author bio, 
   byline) behind it, so the name promised more than the factor actually checked.

#### 0.3.9

 * Fixed a false-positive risk in the risk-category and commercial-keyword detection(
   External Link Risk, Commercial Density, Sponsored Disclosure): a keyword was 
   previously matched as a plain substring anywhere in a domain or link text, so
   an unrelated word that happened to contain the same characters (for example inside
   a longer word) could be flagged. Matching now requires a real word boundary.

#### 0.3.8

 * Added Support, Donate and Write a review links to the plugin’s row on the Installed
   Plugins screen, the same convenience links many WordPress.org plugins show (this
   isn’t automatic: each plugin has to add it in its own code).
 * Added a `wp algoradar scan` WP-CLI command that runs a scan to completion from
   a real system cron job, for hosting where WP-Cron isn’t reliable enough and the
   browser-driven fallback isn’t practical either (it requires a page kept open).
   Fully optional: WP-Cron and the browser fallback keep working exactly as before
   if you don’t use it.

#### 0.3.7

 * Added the WordPress.org listing assets: plugin icon, banner and 4 admin screenshots.
 * Re-tagged to pick up the Donate link added after 0.3.6 was tagged: the plugin
   page reads its readme from the Stable tag’s own folder, not from trunk, so a 
   change committed only to trunk after a tag never appears on the public page until
   the next tag.

#### 0.3.6

 * Added an “External services” section to this readme documenting the optional 
   Google Search Console connection: what is sent to Google, when, and links to 
   Google’s own Terms of Service and Privacy Policy.
 * Removed the pre-built translation files from the plugin package. WordPress.org
   generates and serves translations for approved plugins itself once volunteer 
   translations exist, so shipping them here was redundant.

#### 0.3.5

 * Fixed the actual cause of the scan getting permanently stuck right at the end
   of site indexing (100% of contents read, never moving to the analysis phase) 
   on sites with a large number of published, long-form contents: finding duplicate/
   near-duplicate pages compared the full set of text fingerprints of every single
   page against every other page’s, all held in memory at once. A long article can
   produce hundreds or thousands of these fingerprints, and multiplied by tens of
   thousands of pages this could exceed the memory PHP is allowed to use, crashing
   the request outright with no valid response, exactly where this kept happening.
   Each page’s fingerprint is now reduced to a small fixed-size sample (a standard
   technique for comparing large numbers of documents cheaply) that still reliably
   identifies near-duplicate pages, cutting the memory this step needs by roughly
   80-90x. As a safety net on top, this step now also recovers instead of leaving
   the scan stuck if something about it still fails unexpectedly, and a runaway 
   number of pages to compare against each other is capped rather than left unbounded.
 * A scan already stuck at this exact point (100% indexed, stuck) cannot recover
   on its own even after updating, because the comparison data it already collected
   was captured before this fix in the old, unbounded format: start a new scan after
   updating.

#### 0.3.4

 * Fixed the same “error during the scan” from 0.3.3 still appearing on very large
   sites, this time during site indexing itself rather than scoring: reading and
   analyzing 200 contents in one batch (no HTTP requests involved, just database
   reads and text processing) can still take longer than expected on some hosting/
   content combinations, and a batch that ran long could hit the same server execution-
   time wall the 0.3.3 fix addressed only for the scoring phase. Indexing batches
   now also stop and hand off the rest of their work if they run long, the same 
   safeguard already applied to scoring in 0.3.3.

#### 0.3.3

 * Fixed the actual cause of “An error occurred during the scan” appearing partway
   through, on sites with a large number of published contents: the scoring phase
   claimed a full batch of pages upfront and analyzed every one of them (including
   a real HTTP check per page) before answering, with no limit on how long that 
   could take; a batch that included several slow or unresponsive pages could run
   past the server’s execution time limit, killing the request before it could reply,
   which the browser then reported as an error instead of quietly continuing. Batches
   now also stop and hand off the rest of their work if they run long, regardless
   of how many pages were assigned to them.
 * Fixed the same kind of issue at the point site indexing finishes: finishing the
   index used to write its duplicate-content findings one page at a time, meaning
   a site with tens of thousands of contents made just as many individual database
   updates in that single moment. This is now done in bulk, a page’s write is no
   longer lost after a slow batch (it’s picked up again immediately, not after the
   usual 10-minute safety window), and a batch that still fails to reply now gets
   a few automatic, increasingly-spaced retries before showing an error, instead
   of stopping at the very first blip.

#### 0.3.2

 * Fixed the resumed background execution added in 0.3.1: opening (or reloading)
   the Scan page while a scan was already running only read and displayed its status,
   without also driving it forward, so on hosting where WP-Cron isn’t reliable enough
   for a scan that needs many sequential batches, progress could stall after the
   very first batch. The page now also resumes actively processing batches in that
   case, exactly like right after clicking “Start”, instead of only showing numbers
   that don’t move.
 * Fixed the progress display mixing counts from different phases: the number of
   contents read during site indexing and the number of pages scored are two different
   things, and adding them together could show a confusing, occasionally over-100%
   progress. The bar and text now always reflect the current phase’s own count.

#### 0.3.1

 * Fixed a scan that could never complete on sites with a very large number of published
   contents: creating the scan inserted one database row per content and read every
   content’s text in a single request to build the internal-link/duplicate-content
   index, which on a large site could exceed the server’s execution time (or a proxy’s
   request timeout) before the scan was even handed off to background processing,
   leaving it stuck at 0% forever. Row creation is now done in bulk instead of one
   query per content, and the site index is now built in the same small background
   batches already used for scoring, so a scan never does more than a few seconds
   of work in a single request regardless of site size.
 * Added a safeguard for the rare case a scan still gets interrupted mid-run (e.
   g. a genuine server crash): if a scan shows no progress at all for more than 
   10 minutes, the Scan page now offers to start a new one instead of staying stuck
   indefinitely.
 * The Scan page now shows live progress (including during the initial site-indexing
   step) without needing a manual reload, when a scan is already running when the
   page is opened or reloaded.

#### 0.3.0

 * Fixed a race condition in background batch processing: the immediate loopback
   trigger and its wp_cron safety net could, if close enough together, both pick
   up the same pending rows and analyze them twice. Batches are now claimed atomically
   with a per-call token, and rows stuck mid-batch by a server timeout are automatically
   reclaimed after 10 minutes instead of stalling the scan forever.
 * Removed a redundant database query per duplicate page: cluster size is now computed
   once during site indexing and stored on the row, instead of being recalculated
   on every scoring pass.
 * Noindex and canonical are now also read from HTTP response headers (X-Robots-
   Tag, Link), not only from the page’s HTML: some hosting setups and security plugins
   set these only at the header level.
 * Added an optional Page Experience factor using real Core Web Vitals (LCP, CLS,
   INP) from the Chrome UX Report API: off by default, requires your own free API
   key, and simply skips pages without enough real-user data instead of scoring 
   them as if there were no issue.
 * Added a CSV export button on the Pages screen (priority, scores, top suggestion
   for every analyzed URL), useful for handing the list to an editorial team without
   opening each page’s detail individually.
 * Made the external-link risk keyword lists (gambling, loans, adult, pharma, replica,
   commercial keywords) extensible via the `algoradar_risk_categories` and `algoradar_commercial_keywords`
   filters, and documented in the Guide that they’re Italian-language and tuned 
   for Italian-language sites.

#### 0.2.9

 * Removed the Plugin URI header: it was identical to the Author URI, which the 
   Plugin Directory submission form requires to be different. The plugin doesn’t
   have a dedicated landing page of its own, so Author URI (https://www.ceotech.
   it/) is kept as the single point of contact.

#### 0.2.8

 * Added the WordPress.org listing assets: plugin banner and admin screenshots.

#### 0.2.7

 * Added an en_US translation (identical in substance to the existing en_GB one,
   no British-only spellings needed changing). Without it, the large majority of
   English-language WordPress installs, which default to en_US, would have fallen
   back to the plugin’s Italian source strings instead of showing English.

#### 0.2.6

 * The fix in 0.2.5 removed the query’s dynamic placeholder count from being visible
   to static analysis, which flagged it again for a different, unavoidable reason:
   PHPCS cannot verify what a variable holding a full SQL string contains before
   it reaches $wpdb->prepare(). Documented with an inline justification instead 
   of restructuring further, since the value only ever comes from a fixed literal,
   WordPress’s own $wpdb->posts, and dynamic %s/%d placeholders.

#### 0.2.5

 * Fixed a query that chained two $wpdb->prepare() calls into each other (one for
   the LIMIT clause, one for the IN() values): harmless in practice, but confusing
   for static analysis and for anyone reading the code. Now built as a single prepare()
   call with every value in one array.

#### 0.2.4

 * Fixed a missing translators comment on a string with ordered placeholders, and
   a prepared-statement call that PHPCS couldn’t verify as safe because it was split
   across two statements: both are now resolved without changing behavior.
 * Sanitized several $_GET/$_POST reads that were missing wp_unslash() before validation(
   Search Console OAuth routing, AJAX scan engine parameter, settings time window
   and duplicate-similarity threshold).
 * Documented, with inline justification, the direct database queries against the
   plugin’s own custom tables, the SQL table-name interpolation (never built from
   user input), and the local-variable naming in admin view files: patterns the 
   WordPress.org review team already expects from plugins using custom tables and
   included templates.
 * Removed load_plugin_textdomain(), unnecessary since WordPress 4.6 for a plugin
   declaring a Domain Path.
 * Bumped “Tested up to” to the current WordPress version and set the real WordPress.
   org username in Contributors.
 * Translated this readme into English, the language required for the main file 
   in the Plugin Directory; the plugin’s admin interface keeps its existing translations(
   Italian, English, French, German, Spanish).

#### 0.2.3

 * Fixed three factors marked as “severe” (able to force Priority 1 on their own)
   whose formula could never actually reach the required threshold: Canonical Tag(
   a canonical pointing to a completely different domain is now worth 95, not 80),
   Duplicate Content (risk now scales with the actual cluster size: 55 for a pair
   of similar pages, up to 95 for a cluster of 5+ near-identical pages), and Duplicate
   Pattern (added a 95 threshold for clusters of 6+ pages, typical of mass-generated
   content).
 * Lowered the maximum Internal Linking risk from 100 to 75: the factor has not 
   forced priority for a while, but a lower ceiling prevents a simple new or not-
   yet-linked page (the most common case on a site that publishes regularly) from
   still pulling the average score too high.
 * Softened the Commercial Density multiplier (from 40 to 30): a high density of
   commercial links is normal on legitimate review/affiliate sites, so the maximum
   now requires a more pronounced density to be reached.

#### 0.2.2

 * Fixed a calibration bug: an orphan page (0 inbound internal links) or a factor
   disabled with weight 0 in Settings could on their own force Priority 1, even 
   with no real issue present. Every factor is now marked either “severe” (a direct,
   confirmed problem: HTTP errors, noindex, exact duplicates, risky links) or “soft”(
   an indirect or gradual signal): only “severe” factors with a weight greater than
   zero can force maximum urgency; all factors still contribute normally to the 
   weighted average.
 * Optimized content reading during scanning: a single DOM parse per page instead
   of three, and a lighter read during site indexing that only computes the data
   it actually needs. Cuts per-page processing time by roughly 55-60%, especially
   useful on sites with a lot of content.

#### 0.2.1

 * New “Minimal Pro” design for the admin area’s cards: circular gauges for scores,
   rounded corners, subtle shadows, more polished pills and badges, more readable
   tables. No functional changes, styling only.

#### 0.2.0

 * Added 5 new factors to the scoring model: Duplicate Title, Duplicate Meta Description,
   Heading Structure, Canonical Tag (Core Exposure Score) and Sponsored Disclosure(
   Spam Exposure Score).
 * Recalibrated all default weights, with documented reasoning in the code for each
   value.
 * Removed the “Maximum depth” setting, which was never actually connected to any
   real logic (the plugin reads published content from the database, it doesn’t 
   follow a depth-based crawl).
 * Added a safety ceiling (200) to “URLs per batch” to avoid server timeouts on 
   batches that are too large; it doesn’t affect the total number of pages that 
   can be analyzed, which stays unlimited by default.
 * Added pagination to the Pages page (it used to show at most 200 results with 
   no way to see the rest on larger sites).
 * Fixed a bug where links with href=”javascript:…” were counted as internal links.
 * Added multilingual support: .pot file and complete translations in English, French,
   German and Spanish. More EU languages planned for future versions.

#### 0.1.3

 * Set Plugin URI to https://www.ceotech.it/.
 * Created the plugin icon (an eye with a radar detail) for the WordPress.org listing,
   in assets/icon.svg, icon-128×128.png and icon-256×256.png.

#### 0.1.2

 * Updated Plugin URI to an unresolvable placeholder domain (no longer points to
   a real site).
 * Added the “Guide” page with step-by-step instructions for first-time users.
 * Added a support contact (info@ceotech.it) to the Guide page and the readme.
 * Corrected the description of background execution: it uses WP-Cron with chained
   batch execution, not the Action Scheduler library.

#### 0.1.1

 * Fixed a missing database schema update when the plugin is replaced on an already-
   active installation (could cause scans to get stuck at 0 URLs).

#### 0.1.0

 * First development version: plugin structure, data tables, admin pages, settings.
   The scanning and scoring engine will be added in later versions.

## Meta

 *  Version **0.3.14**
 *  Last updated **5 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.0 or higher **
 *  Tested up to **7.1.2**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [content audit](https://wordpress.org/plugins/tags/content-audit/)[google](https://wordpress.org/plugins/tags/google/)
   [Search Console](https://wordpress.org/plugins/tags/search-console/)[seo](https://wordpress.org/plugins/tags/seo/)
   [technical seo](https://wordpress.org/plugins/tags/technical-seo/)
 *  [Advanced View](https://wordpress.org/plugins/algoradar/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/algoradar/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/algoradar/reviews/)

## Contributors

 *   [ Francesco Palmieri ](https://profiles.wordpress.org/ceotech/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/algoradar/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://paypal.me/ceotechit)