=== Dutch Local Business Schema, KVK and VAT ===
Contributors: theseo
Tags: local seo, schema, structured data, localbusiness, nap
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

LocalBusiness structured data with the fields a Dutch company has, plus a check that your name, address and phone match everywhere.

== Description ==

Structured data for local businesses is not new. Structured data that knows a
Dutch company has a Chamber of Commerce number, a VAT identification number
and customers who pay with iDEAL is.

This plugin does two things. It publishes one complete, valid LocalBusiness
node built from what you fill in. And it reads your own site back to find the
places where your phone number, your postcode or the spelling of your name
does not match the details you entered. That second part is the boring half of
local SEO and the half nobody does: on most sites there is still an old mobile
number somewhere, and nobody knows where.

= What goes into the structured data =

* Business name, and the statutory name when it differs
* Legal form, published as an additionalProperty
* Chamber of Commerce number, published as an identifier with propertyID KVK
* VAT identification number, published in the schema.org property vatID
* Street, postcode, town and country
* Phone number and e-mail address
* Coordinates, when you fill in both
* Price range
* Opening hours, up to three blocks per day for a lunch break
* Days that differ, with the Dutch public holidays addable in one click
* Service area, per town or per postcode area
* Payment methods, including iDEAL, Bancontact, debit card and on account
* One of 39 schema.org business types: LocalBusiness itself, plus 38 real
  subtypes of it. Nothing in the list is invented

Empty fields are left out. Structured data with an empty property in it is
worse than structured data without it.

= The consistency check =

Reads your published items, the text of your widgets and your menus, and
compares:

* every phone number that starts with 0, +31 or 0031 and has nine to eleven
  digits
* every postcode written as four digits and two capitals
* every spelling of your business name that is not letter for letter the one
  you entered

What comes out is a list of differences with a link to the place where each
one stands. The plugin never edits your content. A long order number can end
up in the list as a wrong hit; that is a limit of reading text and the screen
says so.

= Two plugins publishing the same thing is worse than one =

If Yoast Local SEO is active, or Rank Math with a local business type set,
this plugin stays silent and tells you why. That check is on by default and
you can switch it off. Only signals that can actually be measured are used,
and the screen names the one it found, so nothing is based on guessing.

Developers can override it with the `theseo_lokaal_schema_conflict` filter,
and change the finished node with `theseo_lokaal_schema_node`.

= Privacy and outgoing traffic =

There is none. No account, no API key, no call to any register, no tracking.
The Chamber of Commerce number and the VAT number are checked on shape only,
by a regular expression in the plugin itself. Everything you fill in stays in
your own database, in one option row. The result of the consistency check is
parked in a transient for one hour, because it is a snapshot and not an
archive.

Deleting the plugin removes the option and the transient. Deactivating keeps
them.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/` or install the zip
   through Plugins, Add New, Upload Plugin.
2. Activate it.
3. Go to Settings, Local business, and fill in the business details. As soon
   as the name, street, postcode and town are there, the structured data is
   published.
4. Check the Settings tab to choose where it appears and to read the finished
   JSON-LD word for word.
5. Run the consistency check on the last tab.

== Frequently Asked Questions ==

= Does it check my Chamber of Commerce number against the register? =

No. It checks the shape, eight digits, and nothing else. Checking against the
register means calling an outside service, and that is not what this plugin
does.

= Why is the VAT number not checked with arithmetic? =

Because since 2020 the VAT identification number of a Dutch sole trader is
drawn at random. There is no check digit left to verify. The shape is checked,
NL, nine digits, the letter B, two digits.

= I use Yoast or Rank Math. Do I get two LocalBusiness blocks? =

No. The plugin looks for Yoast Local SEO and for Rank Math with a local
business type set, and stays silent when it finds one. The admin screen says
which one it found.

= Can I publish it on every page? =

Yes, that is one of the three choices. The front page only is the default,
because that is where a search engine expects it.

= How many items does the consistency check read? =

The 500 most recently changed published items, adjustable between 50 and 5000
on the Settings tab. The result screen says how many were read out of the
total, so the number is never left to the imagination.

= Does it change my content when it finds something? =

No. It reports. Repairing is your decision and your edit.

= Which WordPress versions has this been tested on? =

The header says 6.8. That is the version this release was written against.
The PHP is checked for syntax on 7.4 through 8.5 and the logic of the opening
hours, the holidays and the pattern checks was tested against fixed examples,
but this release has not yet been run through a full manual test on a live
site. The header will be raised when it has been.

== Changelog ==

= 1.0.0 =
* First release.
* LocalBusiness structured data with KVK, VAT, legal form, opening hours,
  exception days, service area and payment methods.
* Dutch public holidays addable in one click, calculated in the plugin itself
  so no PHP calendar extension is needed.
* Consistency check over published items, widgets and menus.
* Detection of Yoast Local SEO and Rank Math to avoid a duplicate node.
* No outgoing requests, everything in one option row, full cleanup on
  uninstall.

== Upgrade Notice ==

= 1.0.0 =
First release.
