=== Ptero SEO ===
Contributors: ptero
Tags: seo, google news, schema, sitemap, discover
Requires at least: 6.0
Tested up to: 6.7
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Editorial-grade SEO for WordPress: a real Schema.org graph, XML and Google News
sitemaps, News and Discover compliance tooling, and freshness protection.

== Description ==

Ptero SEO is built for publications. It covers the on-page basics every SEO
plugin handles, and then does the things news sites actually need and rarely
get: a Google News sitemap that respects Google's two-day window and 1,000-entry
limit, a per-article compliance checker, and protection against the modified and
publication dates drifting for no editorial reason.

**What it does**

* **On-page** — SEO title and meta description independent of the post title,
  canonical URLs, full robots control (`index`/`noindex`, `follow`/`nofollow`,
  `noarchive`, `nosnippet`, `max-snippet`, `max-image-preview`,
  `max-video-preview`), Open Graph and X/Twitter cards, and template variables
  such as `%title%`, `%primary_category%`, `%author%`, `%sitename%` and
  `%currentyear%` per post type, taxonomy and archive.
* **Schema** — one JSON-LD `@graph` per page, never microdata sprinkled through
  the markup. `WebSite`, `WebPage`, `Organization`, `Person`, `ProfilePage`,
  `BreadcrumbList`, `Article`/`NewsArticle`/`BlogPosting`, `ImageObject`,
  `VideoObject`, plus optional `FAQPage`, `Product`, `SoftwareApplication`,
  `Event` and `LocalBusiness`. Entities reference each other by stable `@id`.
* **Sitemaps** — `/sitemap_index.xml` with separate sitemaps per post type,
  taxonomy and authors, automatic splitting, `noindex` content excluded,
  canonical URLs only, and accurate `<lastmod>`.
* **Google News** — an optional `/news-sitemap.xml` containing only qualifying
  articles from the last 48 hours, capped at 1,000 entries per file with extra
  files created automatically, `news:publication`, `news:name`, `news:language`,
  `news:publication_date` and `news:title`. Publication dates come from the
  original post date and never change because someone edited the article.
  Per-article exclusion, plus global exclusion of Opinion, Sponsored, Press
  release and Evergreen content.
* **News compliance checker** — per article: visible publication date and time,
  author byline and profile URL, author biography, featured image, image size,
  unique canonical, valid `NewsArticle` schema, indexability, date sanity and a
  readable article body. Site-wide: About, Contact, editorial policy, ownership
  and funding, corrections policy, advertising disclosure, author pages and
  biographies. These are reported as *Google News transparency recommendation
  missing*, not as a ranking checklist — because they are not one.
* **Freshness protection** — detects when a plugin, import or bulk edit changes
  `post_modified` without the content actually changing, and keeps reporting the
  real `dateModified`. Warns when a publication date is moved forward on an old
  article. Editors classify changes as *Minor correction*, *Substantial update*
  or *Republished*, and the schema follows.
* **Discover** — forces `max-image-preview:large` on news articles, warns when
  featured images are under 1200px wide, flags logos and placeholders used as
  article images, flags text-heavy thumbnails, and shows a 16:9 card preview.
* **Editorial analysis** — focus keyphrase placement in the title, H1,
  introduction, slug, subheadings and alt text, with no keyword density target.
  Detects stuffing, repeated sentence openings, excessive passive voice, long
  sentences and paragraphs, weak heading structure, duplicated headings, a
  missing introduction, and missing internal or external links. For journalism:
  source attribution, quote and source balance, primary-source links, author
  expertise, update disclosure and original reporting indicators.
* **Trust & Editorial Signals** — not called an E-E-A-T score, because Google
  does not publish one. Checks whether the signals Google's documentation
  actually discusses are present.
* **Internal linking** — related-article suggestions with anchor text, orphan
  detection, over-linked pages, broken internal links, links pointing at
  redirects, topic-cluster and category silo analysis.
* **Redirects** — 301, 302, 307, 308, 410 and 451, regex rules with `$1`
  backreferences, automatic 301 when a published slug changes, loop and chain
  detection before saving, and a 404 log ordered by hit count.
* **Indexing controls** — per post, page, category, tag, author, date archive,
  search results, attachment page and custom post type. Internal search is
  noindexed by default, attachment pages are redirected to their parent, staging
  environments are blocked automatically, and the plugin warns loudly if
  *Discourage search engines* is switched on or robots.txt blocks Googlebot.
* **Images** — missing alt detection, oversized file detection, tiny featured
  image detection, unreachable and robots-blocked image URLs, image metadata in
  schema and sitemaps, and `fetchpriority="high"` on the hero image so lazy
  loading does not wreck LCP.
* **Breadcrumbs** — visible HTML trail and matching `BreadcrumbList` JSON-LD
  built from the same data, via shortcode, template tag or block.
* **Site Kit by Google** — if Site Kit is already connected to Search Console,
  Ptero SEO uses that connection automatically. No second sign-in, no OAuth
  client, no credentials of its own. Site Kit only exposes web search data, so
  Discover and Google News report as unavailable on that route rather than
  showing web numbers under the wrong heading; connect Search Console directly
  to add them, and the direct connection takes over automatically.
* **Search Console** — connect with your own OAuth client, see clicks,
  impressions, CTR, average position, top queries and top pages, separated by
  Web Search, News, Google News and Discover where Search Console exposes them.
  Performance appears in the post editor.
* **Content decay** — finds pages that used to perform and no longer do. For
  news articles it recommends a follow-up or a substantial update, and never
  suggests re-dating the article.
* **Technical audit** — Critical / Warning / Recommendation, not a score.
* **Core Web Vitals** — PageSpeed Insights integration that reports rather than
  replacing your caching or optimisation stack.
* **Conflict detection** — warns when Yoast, Rank Math, All in One SEO, SEOPress
  and others are active, explains exactly what will be duplicated, and imports
  their data.
* **Roles** — separate SEO Manager, Editor and Writer capabilities, so writers
  can edit keyphrases and descriptions without being able to noindex the
  publication.
* **Optional AI assistant** — suggests titles, descriptions, related entities,
  schema descriptions and alt text. It proposes; it never publishes, and it
  never rewrites journalism. AI output is visually distinct from technical
  findings throughout.

**Multisite**

Every site on a network keeps its own settings, sitemaps, redirects, link graph
and reports. Network administrators can set defaults for the whole network and
lock individual settings so site administrators cannot change them. Credentials
— API keys and Search Console tokens — are always per site and can never be set
network-wide. New sites are provisioned automatically when the plugin is network
activated.

**What it deliberately does not do**

* No `meta keywords` tag. Google ignores it.
* No second caching layer. It reports Core Web Vitals and leaves delivery to
  Cloudflare, LiteSpeed, WP Rocket or whatever you already run.
* No "E-E-A-T score". Google does not publish one, so neither does this.
* No claim that any checklist guarantees inclusion in Google News or Discover.

== Installation ==

1. Upload the `ptero-seo` folder to `/wp-content/plugins/`.
2. Activate it, or network activate it on a multisite install.
3. Go to **Ptero SEO → Settings** and set your publisher name and logo.
4. If you publish news, enable **Google News SEO** and set your publication name
   to match Google Publisher Center exactly.
5. Submit `/sitemap_index.xml` once in Google Search Console.

If you are migrating, run **Ptero SEO → Tools → Import** before deactivating
your previous SEO plugin.

== Frequently Asked Questions ==

= Does this ping Google when I publish? =

No, because Google removed that endpoint. Bing removed theirs too. The plugin
advertises your sitemaps in robots.txt and submits changed URLs to IndexNow,
which Bing, Yandex and Seznam still use. Submit your sitemap index once in
Search Console and Google will recrawl it on its own schedule.

= Why does my modified date not change when I edit a post? =

If you marked the change as a *Minor correction*, that is deliberate: a typo fix
should not tell Google the article is new. Choose *Substantial update* when the
article genuinely gained new information.

= Can I run this alongside Yoast or Rank Math? =

You can, but you should not. Both will output canonical tags, schema and Open
Graph data, and search engines will have to pick between them. Import your data,
check a few pages, then deactivate the other plugin.

= Does the compliance checker guarantee I will appear in Google News? =

No, and it does not claim to. It checks whether the transparency and technical
recommendations Google publishes are met. Inclusion is Google's decision.

= What data does the plugin send anywhere? =

Ptero SEO uses [Freemius](https://freemius.com) to handle licensing, updates and
opt-in diagnostics. Nothing is sent until you explicitly agree during activation,
and you can skip the opt-in entirely and still use every free feature. If you do
opt in, Freemius receives your site URL, WordPress and PHP versions, the plugin
version and your administrator name and email address, so that support requests
and licence keys can be matched to your site. You can revoke this at any time
under **Ptero SEO → Account**.

Freemius terms: https://freemius.com/terms/
Freemius privacy policy: https://freemius.com/privacy/

Licence holders additionally exchange the licence key and the site URL with
Freemius on activation and on each update check, which is what makes automatic
updates of the paid version work.

== Third-Party Services ==

This plugin relies on the following external services.

* **Freemius** — licensing, checkout, automatic updates and (opt-in only) usage
  diagnostics. Contacted at `api.freemius.com`.
  Terms: https://freemius.com/terms/ · Privacy: https://freemius.com/privacy/
* **Google Search Console API** — only when you connect an account under
  **Performance**, and only to read your own search analytics.
* **Google PageSpeed Insights API** — only when you run a speed report.
* **IndexNow** — only when URL submission is enabled, to notify Bing, Yandex and
  Seznam that a URL changed.

== Changelog ==

= 1.0.0 =
* Initial release.
