Description
Megop SEO is five tools that share one index, so they agree with each other instead of fighting.
Written and maintained by محمد قاسمی (Mohammad Ghasemi), Tehran, Iran.
Most SEO plugins are written for English and translated afterwards. This one is written the other way round. A Persian phrase can be spelled several ways that look identical to a reader and completely different to a computer – an Arabic character where a Persian one belongs, a zero-width non-joiner instead of a space, Arabic-Indic digits instead of Latin ones. Every plugin that matches text literally treats those as different phrases. This one folds them together before matching, using an offset map so your content is never rewritten, only read.
How it is tested
Every release runs against a live Persian WooCommerce site with several thousand posts before it is packaged, not only against a clean install. That is deliberate, and it is where the findings come from.
One example, because it is the kind of thing a checker cannot see. A template in the linking screen declared a small helper function at file level. PHP registers a function declared in an included file globally, whatever scope the include ran in, so the second time that template was rendered inside one request the whole screen died with Cannot redeclare. It is a compile-time error, so try/catch cannot reach it, and the site’s own error log had recorded it three times on real page loads. No static analyser flagged it and no clean-install smoke test triggered it, because rendering the template twice is what triggers it. The helper is a static method now, and no template in this plugin declares a function at all.
A second example, from the same site and the same kind of blindness. A crawl reported twenty internal 301 links inside published posts; Link Nurse had reported none of them, on any scan, ever. The cause was one boolean. Redirect handling sat behind a setting whose own label reads “Rewrite 301/302 to final 200 destination” – a repair switch, wired as a detection gate. With it off the scanner never resolved where a 301 went, so the classifier had no destination to judge and returned “healthy” for every redirected link on the site. Nothing errored, nothing was logged, and the dashboard was confidently wrong. Detection and repair are separate now, and the classifier is covered by a test that runs every case with the switch in both positions.
A third example, and the largest. The same crawl showed forty links Link Nurse had never reported. Not a classification problem this time: the extractor collected every href and src on the page and then dropped anything that did not begin with http, one line later. A link written as /product/name/ – the form the editor produces when you pick a page from the link dialog – never reached the checker at all. Counted the way the scanner reads content, 332 of the 1,373 links on that site were stored that way, spread across 188 of its 364 published items. A quarter of every link and half of every page, invisible on every scan since the module was written, with nothing on the dashboard to suggest it. Relative links are resolved against the page they sit on now, and the repair keeps the form the author wrote.
The same habit produced the rest of the list: a settings form that reported success while saving nothing because the browser stringified an object into the request; a bulk editor that emptied variable-product prices because an empty field was read as “clear” rather than “leave alone”; a Jalali date reaching a SQL comparison and returning zero rows on a site with 66,000 recorded visits. Each of those is in the changelog with what caused it.
Works alongside Rank Math
The SEO title and meta description this plugin edits are Rank Math’s own fields (rank_math_title and rank_math_description). If Rank Math is not installed, those two columns in the bulk manager still save, but nothing renders them in your page source, so they have no effect. The redirect hand-off also looks for Rank Math and steps aside when it finds it, so the two never write competing redirects.
Everything else – internal linking, broken-link repair and analytics – works on its own and needs no other SEO plugin.
If you use a different SEO plugin, the two title and description columns will not do what you expect. Everything else will.
The five modules
Each module can be switched off. A module that is off registers no hooks at all: no cost, no menu entry, no route. Its data is never touched by switching it off.
1. Seo Bulk Manager. A spreadsheet view of your site. Edit the H1, the SEO title, the meta description, the body content and the featured image across many rows at once, without opening a single post. WooCommerce prices are editable too, including variable products – and an empty price field means “leave this alone” rather than “clear it”, because writing an empty value to every variation would wipe a catalogue. Each row has its own find-and-replace, and Elementor content is kept in step so an edit you make here is the edit visitors see.
2. Seo Auto Link. Give any post, page, custom post type or term a keyword, and the engine links every mention of that phrase across the site.
It starts in shadow mode: it builds the whole index and shows you exactly what it would do, while not a single link reaches a visitor. You switch it to live when you are satisfied, not before.
Links are injected at render time from a prebuilt index, so the page view does no matching work at all – the heaviest page on a 300-page site costs about seven milliseconds. Links are never placed inside headings, existing links, code, scripts, forms, buttons, SVG, shortcodes or HTML attributes.
Matching is longest-phrase-first with range locking, so two keywords can never overlap, and a page can never link to itself. Caps are available per page, per target and per paragraph, and all of them are off by default – the measure is what your content needs, not a number someone picked.
It also finds the links you wrote by hand years ago. A manual link blocks the engine, because the engine refuses to look inside an existing link – so those phrases sit outside every report and never update when a destination moves. The pattern finder lists them, shows whether each one agrees with your keyword map, and converts them in bulk.
Reports cover anchor-text conflicts, targets nothing links to, and rows left behind by an older index. Blacklisted pages keep receiving links and stop giving them out, which is deliberate: a landing page should hold its authority rather than spend it.
Nothing is lost when you leave. Deactivating the plugin writes every link permanently into your content. Reactivating takes them back out and hands control to the engine again. Uninstalling keeps the backups that make that reversible. Before any of this touches your content, a twenty-check self-test has to pass, the tag balance has to be exactly right, and the plain text before and after has to be identical.
3. Search Console. Connect your own Google service account and see, per page, which searches Google already shows you for – and which of those words are not actually on the page. Green means the phrase is present, yellow means the words are there but scattered, red means something is missing. Red is where the opportunity is, because Google is already showing that page and nobody is clicking.
Index status asks Google, one URL at a time, what it knows about each of your pages, and groups the answers the way Search Console groups them. Pages Google has already indexed, pages excluded by a noindex tag and pages blocked in robots.txt are never asked again, because that answer will not change.
The effect report keeps a control group, so you can tell an edit that worked from a week when the whole site went up.
This reads Google’s index. It does not request indexing – Google publishes no API for that, and the button lives only inside Search Console itself. What it can do instead is find the pages Google has never discovered and push them to the front of the internal-linking queue, which is the discovery route Google does document.
4. Link Nurse. Finds broken and redirected links across posts, pages, taxonomies, custom fields and menus, and is aware of Elementor and WooCommerce markup. Results are grouped by cause, repaired in batches, and every repair can be undone one item at a time from a backup kept in post meta. 4xx results can be re-checked with a browser user-agent to cut false positives, and functional links – cart, wishlist, login – are protected by query key so they are never rewritten. Results export to XLSX. Sixteen built-in tests run against in-memory data, so you can confirm nothing regressed without touching your site.
5. Internal Analytics. Self-hosted visit and event tracking. No data leaves your server and no third party is contacted. It records the requested path, the referrer, a coarse device type and a daily-rotating hash of the visitor’s address. It sets no cookie and stores no raw IP address. Screens cover live visitors, per-page performance, traffic sources and custom events, all exportable as CSV. Switching the module off stops recording and leaves every existing row untouched.
Persian and Arabic
Every screen reads in English, Persian or Arabic, and each person chooses for themselves – the choice is stored per user and applies only to this plugin. WordPress, your theme and every other plugin keep the language the site set. The JavaScript is translated too, so confirmations and live counters follow the same choice.
Dates are handled carefully: on a site with a Persian calendar plugin, wp_date() returns a Jalali date, and a Jalali string in a SQL comparison silently returns nothing. Every date that reaches a query here is built in a calendar-neutral way. Only what you read on screen is localised.
External services
This plugin contacts nothing unless you configure it to.
Google Search Console API – used only when you upload your own Google service-account key on the Search Console screen. The plugin then sends your site’s property name and date ranges to www.googleapis.com, sends individual page URLs of your own site to searchconsole.googleapis.com when you use the index-status screen, and sends a signed token request to oauth2.googleapis.com to authenticate. No visitor data and no page content is sent. Remove the key and the calls stop.
Google API Terms of Service: https://developers.google.com/terms
Google Privacy Policy: https://policies.google.com/privacy
An AI endpoint of your choosing – optional, and off unless you fill in a base URL, key and model name on the Search Console settings screen. When enabled, the plugin sends the text of the page being worked on and the search queries it is meant to cover to the endpoint you named, and writes the returned text into that page as a draft edit you can undo. The plugin ships with no endpoint, no key and no default provider; whichever service you point it at, its own terms and privacy policy apply. Leave the fields blank and no request is ever made.
No other outbound request is made by this plugin.
Author
Megop SEO is written and maintained by محمد قاسمی (Mohammad Ghasemi) in Tehran, Iran.
It began as three separate plugins built for real Persian sites over several years – internal linking, broken-link repair and analytics – which were merged once it became clear they were solving one problem badly in three places instead of one problem well in one. The Persian matching rules in it come from mistakes made on live sites, not from a specification.
- Web: megop.org
- About the author: megop.org/founder-bio
- Email: jobshiveh@gmail.com
- Telegram: @sanjesh1
Bug reports and feature requests are welcome on the support forum here, in English or Persian.
Installation
- Upload the plugin folder to
/wp-content/plugins/, or install it through the Plugins screen. - Activate it. The linking engine starts in shadow mode, so nothing on your site changes yet.
- Go to Megop SEO and add a keyword to a page, then build the index.
- Review what the engine would do, and switch the engine to live when you are satisfied.
For the SEO title and meta description columns in the bulk manager to appear in your page source, install Rank Math – those are its fields.
The Search Console features are optional and need a Google service account of your own. The screen walks you through creating one and accepts the key file as an upload.
FAQ
-
What is internal linking, and why does it matter?
-
An internal link is a link on one page of your site pointing at another page of the same site. It is the cheapest SEO work there is, because you own both ends.
Internal links tell a search engine which of your pages exist, how they relate, and which ones you consider important. A page nothing links to is a page a crawler may never reach. A page fifty pages link to, with the same phrase each time, is a page you have told the search engine what it is about. And a reader who follows one is a reader who stayed.
The work is dull, which is why almost nobody does it by hand past the first hundred posts. That is the job this plugin automates.
-
Will the linking engine slow my site down?
-
No. Matching happens once, when the index is built, and never again. Serving a page is a byte-search for anchors that were decided in advance, with no folding, no regular expressions and no keyword map in memory.
On a real 300-page site the heaviest page costs about seven milliseconds. That number is measured, not estimated, and you can measure it yourself on your own content.
-
Will it improve my rankings?
-
Nobody can promise that, and anyone who does is selling something. What can be said is narrower and true: internal linking is a basic part of on-page SEO, search engines use it to find and interpret pages, and this plugin does it consistently across a whole site instead of the twenty pages you had the patience for.
-
Does the plugin change my content?
-
Not while it is active. Links are injected as the page renders, from a prebuilt index. Your
post_contentin the database is exactly what you wrote.Deactivating is the one moment it does write, and it writes on purpose: every link is made permanent in your content so that switching the plugin off does not silently strip your internal linking. Reactivating takes them straight back out and returns control to the engine. The backups that make that reversible are kept even through uninstall.
-
What happens if I delete the plugin entirely?
-
The links stay, because deactivation wrote them into the content first. If deactivation was somehow skipped, the uninstaller does the same job as a last line of defence. Nothing you can do from the Plugins screen loses your internal links.
-
Does it work with content built by shortcodes or a page builder?
-
Shortcodes, yes. Elementor, yes, and that one needed real work: an Elementor page keeps its real content in post meta and treats
post_contentas a cache it regenerates, so editingpost_contentthere does nothing you can see. The plugin reads and writes the meta on Elementor pages, and the bulk editor keeps both in step. -
Can I stop the engine linking on particular pages?
-
Yes, two ways. A checkbox in the editor excludes one page, and a blacklist screen holds a list. Both are respected, and the screen shows the union of the two so a page excluded from the editor is not invisible in the list.
An excluded page still receives links from elsewhere; it only stops handing them out. That is the intended behaviour for a landing page, and no tool in the plugin will rewrite a blacklisted page’s content.
-
Can I control how many links appear?
-
Yes, per page, per target and per paragraph, plus a cap on incoming links per target. All four are off by default. The right number is whatever the content carries, not a figure someone picked, so the plugin asks you to turn a cap on rather than imposing one.
There is also a Wikipedia-style rule, on by default: link a given phrase once per page, not every time it occurs.
-
What stops it linking a phrase inside a heading or another link?
-
The tokeniser. Before any matching happens the page is split into the ranges where a link may legally go. Twenty tags are excluded, among them
a,h1toh6,script,style,code,pre,textarea,button,select,option,svg,canvas,iframe,formandlabel, plus HTML comments, shortcodes and everything inside an attribute.This is structural, not a setting. There is no configuration in which a nested link can be produced, which is why converting a hand-written link into an automatic one can never leave you with two.
-
I have hand-written internal links from years ago. What happens to them?
-
They are found and listed. This is one of the more useful screens and it exists because of a real problem: the engine refuses to look inside an existing link, so every phrase you linked by hand is invisible to every report, never updates when its destination moves, and quietly blocks the engine on that page.
The pattern finder lists them, tells you whether each agrees with your keyword map, and converts them in bulk. On one real site it found 400 of them where the previous threshold had shown 6.
-
I have hundreds of posts. Do I have to type keywords one at a time?
-
No. Keywords are editable inline in the bulk manager, as chips, for posts and for terms, so you can work down a list of a hundred rows without opening a single editor. Migration from Internal Link Juicer imports its keywords for both posts and terms.
-
Does it work with translation plugins?
-
It does not read a translation plugin’s language tables, so on a multilingual site treat each language’s content as its own set of keywords and targets. The Persian and Arabic folding is character-level and applies wherever those scripts appear.
-
What does the bulk manager actually do that other bulk editors do not?
-
Three things, and they are the reason it was written.
It edits the fields SEO people actually change. H1, SEO title, meta description, body content, featured image, slug, taxonomy terms, parent, status and WooCommerce prices, in one grid, across post types and taxonomies alike.
It edits taxonomies as first-class rows. Almost every bulk editor treats a category as a filter. Here a category archive is a row like any other: it has a title, a description, an SEO title, keywords and incoming links, because to a search engine it is a URL like any other.
It has per-row find and replace, with a corresponding mode. Give it a keyword and a list of replacement lines, and it produces one new draft per line with that substitution applied through the title, the meta and the body together. That is how you turn one well-written page into thirty city pages without thirty rounds of copy and paste.
And it is honest about empty fields. An empty price means leave this alone, not set this to nothing, because the other reading empties a catalogue.
-
Is bulk editing safe on a live shop?
-
Every write is scoped to the rows you selected, WooCommerce variable products are handled through the WooCommerce API rather than by writing meta directly, and the H1 sync into Elementor is a targeted heading replacement, not a content rewrite. The self-test that gates the linking engine also has to pass before anything writes into content.
That said: take a database backup before any bulk operation on a shop. That is true of every tool of this kind, including this one.
-
It clears the cached sitemap of whichever generator you use, reads the sitemap back so the files are rebuilt before a crawler asks, and then, in Link Nurse, follows it: every address the sitemap lists is fetched and anything that does not answer 200 is reported.
That last part finds a class of problem no content scan can reach. A category whose last post was deleted is linked from nowhere on the site, so no scan of your content will ever visit it, and yet there it is in the file you hand to Google. On one real site that check found nine dead category URLs and twenty-one redirects on the first run.
Rank Math, Yoast SEO and All in One SEO are detected, and the WordPress core sitemap is the fallback. The button hides itself on a site with no sitemap at all.
-
Why does Link Nurse report a link my browser opens fine?
-
Usually because the site on the other end blocks robots. Sites like ScienceDirect, Healthline and several journal publishers answer a crawler with 403 while answering a person with the page. The plugin re-checks any 4xx with a browser user-agent before reporting it, and by default only 404 and 410 count as broken, so a bot-wall does not become a false alarm on your dashboard. You can add other codes in the settings if you want them.
-
My internal links are written as /page-name/ rather than full URLs. Are they checked?
-
Yes. They are resolved against the page they sit on, exactly as a browser resolves them, and checked like any other link. That includes protocol-relative links such as //example.com/x. Fragments (#section) and non-http targets (mailto:, tel:, javascript:) are recognised and skipped, because none of them has a status code to check.
When a repair runs, the link is rewritten in the form you wrote it. A site-relative link stays site-relative, an absolute one stays absolute. The plugin checks the absolute form because that is what a status code belongs to, and edits the stored form because that is what is in your content.
-
Why is a redirect shown as Manual instead of being fixed?
-
Because reporting a redirect and rewriting it are two different permissions, and only the second one is optional. Link Nurse always tells you a link is redirected. Whether it rewrites the link for you is decided by the “Rewrite 301/302 to final 200 destination” setting, and while that is off the row is listed as Manual with its destination shown, so you can see the problem and choose what to do about it.
A row is also Manual when the destination could not be established: a chain still redirecting after ten hops, a loop, or a hop the plugin could not reach. In those cases nothing is rewritten, because the plugin will not point one of your links at an address it never verified.
A redirect that ends on an error page is not Manual and not a redirect. It is a broken link wearing a 301, and it is reported as broken with both codes, for example HTTP 301 to 404. That is the usual shape a deleted WooCommerce product leaves behind.
-
Can I undo a repair?
-
Yes, one item at a time or all of them. The original content is kept in post meta before anything is written, so undo restores the exact bytes, not a re-derived guess.
-
Which language will I see?
-
Whichever your WordPress is in. A Persian site shows Persian, an Arabic site Arabic, and everything else English.
You can also override it for yourself: the switch in the plugin header sets the language per person, so an English-speaking developer and a Persian editor can work on the same site each in their own language. The choice applies only to this plugin. WordPress, your theme and every other plugin stay in the site’s language, and the JavaScript strings follow the same choice, so confirmations and counters are not left in English.
-
Do I need Rank Math?
-
For most of the plugin, no. Internal linking, broken-link repair and analytics work on their own.
For the SEO title and meta description columns in the bulk manager, yes – those two fields are Rank Math’s own, and without it they save but nothing outputs them. If you use a different SEO plugin, use its own fields for the title and description and everything else here still works.
-
Will my links disappear if I deactivate the plugin?
-
No. Deactivation writes every link permanently into your content first. Reactivating removes them again and hands control back to the engine, so you can switch either way without losing anything.
-
Does it work with Persian and Arabic text?
-
Yes, and that is the point. Arabic characters are folded to their Persian equivalents, the zero-width non-joiner is treated as a space, and Persian and Arabic-Indic digits are folded to Latin, so a year written two ways is still the same year. Your content is never rewritten to achieve this – the folding happens on a copy, and an offset map puts the link back in the right place in the original.
-
Does it send my content anywhere?
-
Only if you configure the optional AI endpoint yourself, and then only the page being worked on. The Search Console connection sends no content at all – it retrieves your own statistics and, on the index-status screen, asks Google about your own URLs. Everything else, including analytics, stays on your server.
-
Do I need a Google account for the Search Console features?
-
You need your own Google Cloud service account, created under your own Google account. The plugin never uses anyone else’s credentials.
-
Can it ask Google to index a page?
-
No. The URL Inspection API reads what Google already knows; Google publishes no API for requesting indexing, and the button that does it exists only inside Search Console itself. What the plugin does instead is find the pages Google has never discovered and push them to the front of the internal-linking queue.
-
What happens to pages I blacklist?
-
They keep receiving internal links and stop giving them out, and no tool in the plugin will rewrite their content. That is deliberate: a landing page should hold its authority rather than spend it.
-
Why does an index check take so long?
-
Google’s URL Inspection endpoint answers in several seconds per URL. That, not any quota, is the limit. The plugin runs three requests side by side and tells you the real time remaining rather than a guess.
-
Can I switch modules off?
-
Yes. Every module can be switched off, and one that is off registers no hooks at all – it costs nothing. Its data stays exactly where it is, so switching it back on picks up where you left off.
Reviews
There are no reviews for this plugin.
Contributors & Developers
“Megop SEO” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “Megop SEO” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
8.3.0
- Every table and column name that reaches a query now comes from one small class,
Megop_SEO_Db, which builds the name itself from a literal list and hands back an empty string for anything it does not recognise. Nothing in the old code was reachable from a request – the names were already literals – but the claim that the interpolated part is only ever a table name was written in a comment, and a reader had to trace every call site to believe it. It is a property of one file now. The three table helpers in the linking, Search Console and analytics modules all delegate to it, and the CSV exporter’s column list and date column pass through the same check before they are used. - Fixed a query shape that was safe and indefensible at the same time. The index-status screen built a WHERE clause with
$wpdb->prepare()and then concatenated that prepared fragment into a string handed straight toget_results(). Each of the five cases is a whole statement now, prepared once, with its own bound values and a bound limit. - An unknown key given to the Search Console table helper used to raise an undefined-index notice and return null, which then went into a query as an empty table name. It returns an empty string now and the caller stops before the query runs.
- The
phpcs:ignorereasons are rewritten. There were 136 copies of one 300-character paragraph explaining why an interpolated table name was safe. That explanation lives inMegop_SEO_Dbnow, and each suppression carries one short reason. No suppression was removed and Plugin Check still reports no errors and no warnings. - The donate link is removed. It pointed at the site’s front page rather than at a donation page, so it was a second URL to validate for no benefit.
8.0.2
- Fixed, and this is the one that made the scanner look like it was working: Link Nurse could only see links written as full URLs. The extractor collected every href and src on the page and then discarded anything that did not begin with http, one line later. A link written as
/product/name/– the form the editor produces when you pick a page from the link dialog – was gathered, thrown away, and never checked. On the site this plugin is developed against, 332 of the 1,373 links in published content were stored that way, across 188 of its 364 items: a quarter of every link and half of every page, invisible on every scan since the module was written. Ten of them were internal 301s that a crawler had listed and Link Nurse never had. Relative links are now resolved against the page they sit on, exactly as a browser resolves them, and checked like every other link. - A repair now rewrites the link in the form the author wrote it. Both forms are kept for each finding: the absolute one, because that is what a status code belongs to, and the stored one, because that is what has to be found and replaced in the content. A redirect fixed on a site-relative link stays site-relative afterwards – absolute against relative is a house style, and a repair has no business changing it.
- Fragments (
#section) and non-http targets (mailto:,tel:,javascript:) are recognised and skipped instead of being swept up. Protocol-relative links (//example.com/x) are resolved and checked. - Fixed: the XLSX export always ended on a 404. The report was written into
uploads/megop-seo/while the browser was sent touploads/megop-link-nurse/– one folder apart, with the file correct on disk the whole time. Both sides read one constant now, and if the file is genuinely missing the screen says so instead of navigating away from the results. - Report filenames carry a random suffix. A report holds the site’s own link data, and a timestamp-only name in a public uploads folder is guessable.
8.0.1
- Fixed, and this is the one worth reading: Link Nurse could not see a single redirected link. Redirect handling sat behind a setting whose own label reads “Rewrite 301/302 to final 200 destination” – a repair switch that had been wired as a detection gate. With it off, the scanner never resolved where a 301 went, the classifier had no destination to judge, and every redirected link on the site was recorded as healthy. A crawl of one real site listed twenty internal 301s inside published posts that Link Nurse had passed over on every previous scan. Detection now always runs, and the setting decides only whether the link is rewritten for you. A redirect found while rewriting is off is listed as Manual, with its destination and a note naming the checkbox that unlocks it.
- Fixed: a redirect that lands on an error page was reported as healthy. The old branch would only speak if the chain ended in 200, so a 301 into a deleted product – the exact shape WooCommerce leaves behind – fell through as though nothing were wrong. It is reported as broken now, with both codes, for example HTTP 301 to 404.
- Fixed: a redirect whose destination could not be established – a chain still redirecting after ten hops, a loop, or a follow request that failed – was treated as fine, and one fallback path assigned a 200 to a destination it had never reached. Those are reported as Manual with the reason stated, and no link is ever rewritten to a target the plugin did not verify.
- The results table shows the destination on every row that has one, not only on rows the plugin intends to rewrite.
- A finding is no longer dropped because the theme prints the link in a different form. Front-page verification now also matches on path and query, so a link rendered with a different scheme, without www., protocol-relative, or as a host-relative href is still recognised.
- Link Nurse’s heading no longer carries a version number of its own. The unified header was still appending it; only the standalone fallback header had been corrected in 8.0.0.
8.0.0
- Fixed, and this is the one that mattered: the Link Nurse settings form never saved anything. Two separate faults, one on each side. In the browser, the whole settings object was handed to URLSearchParams, which stringified it, so PHP received the literal text “[object Object]” where it expected an array, fell back to defaults for every key and answered “Settings saved” – true of nothing. And the module enqueued its own JavaScript with a frozen version constant instead of the file’s modification time, so the corrected file sat on the server while every browser kept running the copy it had cached months earlier. The first fault made saving impossible; the second made fixing it invisible. Both are gone.
- Saving settings now says so. A green tick on success, a red line with the reason on failure, and the form is repainted from what the server actually stored rather than from what was typed – so if a value was clamped, the field shows the stored one and the confirmation is telling the truth.
- Link Nurse can refresh the sitemap, and then follow it. Clearing a sitemap cache tells you nothing on its own, so the button does the second half too: every address the rebuilt sitemap lists is fetched with Link Nurse’s own checker, and anything that does not answer 200 is reported. This reaches a class of problem no content scan can find – a URL listed for search engines but linked from nowhere on the site, such as a category whose last post was deleted. On one real site it found nine dead category URLs and twenty-one redirects the first time it ran. On by default, switchable in the scan settings.
- Fixed: opening the Link Nurse settings panel pushed the progress bar and every counter a screenful down the page, exactly while a scan was running and they were the thing worth watching. The progress bar sits above the panel now.
- Link Nurse no longer prints a version number of its own in its heading. It was a plugin once and it is a module now; the only version that means anything is the plugin’s.
- Persian and Arabic catalogues cover the new strings, so the sitemap screens read in the site’s language from the first run rather than after the next translation round.
- Deactivating the previous internal-linking plugin, offered at the end of the migration, now requires the capability to manage plugins. It was reachable by anyone the keyword-editor setting allowed, which an administrator can widen to author level – correct for editing keywords, far too wide for switching a plugin off.
- The bulk duplicator’s find-and-replace pairs are sanitised before they reach a post title or body.
- Every remaining inline script tag is printed through WordPress rather than echoed by hand, including the tour’s JSON data block, so nothing that filters, defers or adds a nonce to script output is bypassed.
- The uninstaller now also removes Link Nurse’s own options. Its prefix differs from the plugin’s by one letter, so the existing sweep never reached them.
- The plugin page has been rewritten with a full FAQ covering internal linking, bulk editing, broken links and the sitemap check.
7.5.0
- New: Link Nurse can refresh the sitemap, and then follow it. Clearing a sitemap cache tells you nothing on its own, so the button does the second half too: every address the rebuilt sitemap lists is fetched with Link Nurse’s own checker, and anything that does not answer 200 is reported. This reaches a class of problem no content scan can find – a URL that is listed for search engines but linked from nowhere on the site, such as a category whose last post was deleted. On one real site this found nine dead category URLs and twenty-one redirects that every previous scan had passed over. It is on by default and can be switched off in the scan settings.
- Fixed: Link Nurse settings were never saved. The browser sent the whole settings object as one form value, so PHP received the text “[object Object]” where it expected an array, fell back to the defaults for every key, and answered “Settings saved” – which was true of nothing. Values are now sent in PHP’s own bracket notation and arrive as the array the sanitiser expects.
- Fixed: opening the Link Nurse settings panel pushed the progress bar and every counter a screenful down the page, exactly while a scan was running and they were the thing worth watching. The progress bar sits above the panel now.
- Deactivating the previous internal-linking plugin, offered at the end of the migration, now requires the capability to manage plugins. It was reachable by anyone the keyword-editor setting allowed, which can be widened to author level – correct for editing keywords, far too wide for switching a plugin off.
- The bulk duplicator’s find-and-replace pairs are sanitised before they reach a post title or body.
- Two remaining inline script tags are printed through WordPress instead of being echoed by hand, so anything that filters or defers script output can see them.
- The uninstaller now also removes Link Nurse’s own options. Its prefix differs from the plugin’s by one letter, so the existing sweep never reached them.
7.4.3
- Fixed: a fatal “cannot redeclare” error on the automatic-linking screen. The link statistics template declared a helper function at file level, and PHP registers a function declared in an included file globally even when the include runs inside a method – so any request that rendered that template twice stopped the whole screen. The helper is a static method on the report class now, templates declare no functions at all, and the sort links lost a double escaping along the way: the URL is built once and escaped at the point of output.
7.4.2
- New: a Refresh sitemap button on the bulk manager header. Publishing a post clears the sitemap cache on its own; bulk work does not, and the bulk editor is exactly where a hundred rows change without anyone pressing Publish. The button clears whatever the active generator caches – Rank Math, Yoast SEO, All in One SEO – and then reads the sitemap back over HTTP the way a crawler would, the index and every child file, so they are already rebuilt before a crawler asks for them. It reports how many sitemaps were rebuilt and how many URLs they list. It can be switched off under Settings, and it is hidden on a site with no sitemap at all.
- Dark mode is a saved preference now, and it is offered only where it is real. It used to live in the address bar, so it lasted exactly one click: opening the next module dropped the parameter and the screen snapped back to light. It is stored per person now and it stays. The toggle is printed on the bulk manager alone, because the analytics and broken-link modules declare their palettes on :root, where no wrapper class can reach them, and a switch that darkens the frame while every card inside stays white is worse than no switch at all. Those two modules need a stylesheet rewrite of their own, and that is its own release.
- The header no longer turns round when you change language. Direction is taken from the dashboard, so reading these screens in English on a Persian site translates the words and leaves the logo and the controls exactly where they were.
- The settings screen carried a second row of tabs above the form. The Internal Analytics settings are shown underneath the linking settings now, on the one page, with one navigation instead of two.
- The plugin page now describes all five modules in full, states plainly which parts use Rank Math’s fields and which do not, and names the author. Documentation only – no code changed.
7.4.1
- Fixed: Link Nurse and Internal Analytics both registered their admin page under the same slug. WordPress runs every callback registered on a slug, so opening Internal Analytics also printed the whole Link Nurse screen above it. Link Nurse has its own slug now, and each screen prints only its own content.
- Plugin Check reports nothing at all – no errors and no warnings. Input from the bulk editor, the keyword fields and the Search Console screens is unslashed and sanitized at the point it is read, and every remaining notice is a direct query against one of this plugin’s own tables that now carries a written reason a reviewer can check line by line.
- load_plugin_textdomain() is gone. WordPress has loaded the catalogue by itself since 4.6, and the per-user language switch is unaffected.
7.4.0
- Every string with a placeholder now carries a translators comment, so a translator can see what each one refers to before guessing.
- One message had its placeholders in a fixed order, which meant a translation that reordered them would swap the two numbers. Both are now positional.
- Output escaping reviewed at every point of output; inline scripts now go through wp_print_inline_script_tag().
- unlink(), is_writable() and parse_url() replaced with their WordPress equivalents.
7.3.0
- Every screen can now be read in English, Persian or Arabic, and each person chooses for themselves – the choice is stored per user and applies only to this plugin.
- The JavaScript is translated too. Confirmations, live counters and inline messages follow the same choice as the rest of the screen.
- The Link Nurse module folded into the plugin’s own text domain.
- The Analytics module is translatable for the first time; its screens were hard-coded in Persian.
- Catalogues rebuilt with the standard WordPress tooling, complete in Persian and Arabic.
7.2.0
- Index status: ask Google what it knows about each page, grouped by reason.
- A guided tour on every Search Console screen, switchable off per user.
- Every stylesheet rule now lives in one enqueued file.
7.1.0
- Search Console module: per-page keyword coverage, query-level effect measurement, control group and automatic freezing of pages that fall after an edit.
- Persian and Arabic-Indic digits are now folded during matching. On a mixed-script site this alone corrected about a third of the coverage verdicts.
- WooCommerce price is editable in the bulk manager, including variable products.
- Blacklists and whitelists are no longer cleared when settings are saved from an unrelated screen.
