Settings Screens

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This sub-section’s WordPress bibliography lists the reference material consulted while preparing these pages.

This page was written against WordPress 7.1.3 (released 2026-10-06; 7.1.4, a security release of 2026-10-28, is the version to run in production) and WP-CLI 2.12.0, and checked on 2026-10-28. WordPress 7.1 requires PHP 7.4 at minimum, and PHP 8.3 or newer is recommended. WordPress 7.2 is in beta and planned for 2026-12-08. Every option name, default value and command output below was read from a fresh WordPress 7.1.3 site (official wordpress:7.1.3-php8.4-apache image, MariaDB 11.8, table prefix lp_), and the robots, permalink and Connectors behaviour was observed over HTTP on that site.

The Settings menu is where an administrator sets the site-wide defaults of Lumen Press, the fictitious publisher used throughout this sub-section: its name and time zone, a static home page with the news blog on a separate page, the comment policy, image sizes, clean URLs and the privacy policy page. Every field on these screens is a row in the wp_options table (lp_options for Lumen Press, see Database Schema), so each one can also be read and written with wp option, scripted for staging copies, and checked in code with get_option().

How the Settings screens work

Five of the eight screens are plain HTML forms that post to wp-admin/options.php. That file holds an allow list of option names per screen (the $allowed_options array, filtered by allowed_options), checks the nonce and the manage_options capability, saves only the options in the list for the submitted screen, and redirects back. Plugins add their own fields to these screens with the Settings API (register_setting(), add_settings_field()), which appends to the same allow list; that API is covered in Administration Menus and Settings API.

Menu item File Capability Saved through

General

wp-admin/options-general.php

manage_options

options.php

Connectors (7.0)

wp-admin/options-connectors.php

manage_options

REST API (/wp/v2/settings)

Writing

wp-admin/options-writing.php

manage_options

options.php

Reading

wp-admin/options-reading.php

manage_options

options.php

Discussion

wp-admin/options-discussion.php

manage_options

options.php

Media

wp-admin/options-media.php

manage_options

options.php

Permalinks

wp-admin/options-permalink.php

manage_options

the screen itself

Privacy (4.9.6)

wp-admin/options-privacy.php

manage_privacy_options

the screen itself

The menu order in 7.1 is General, Connectors, Writing, Reading, Discussion, Media, Permalinks, Privacy; plugins usually add their own pages below Privacy. Connectors is a JavaScript application that saves through the REST API, and Permalinks and Privacy process their own form. On a Multisite network, a sub-site’s General screen has no URL fields and no Membership section, because those belong to the network (Multisite Networks).

Part of the same options is exposed by the REST API at /wp/v2/settings to users with manage_options. On the Lumen Press site, the endpoint returned these keys (plus one per active AI provider, see Connectors (7.0)):

title description url email timezone date_format time_format start_of_week language use_smilies
default_category default_post_format posts_per_page show_on_front page_on_front page_for_posts
default_ping_status default_comment_status site_logo site_icon

The REST names are aliases: title is blogname, description is blogdescription, url is home, email is admin_email, timezone is timezone_string and language is WPLANG.

General

General holds the identity of the site and how it formats dates.

Field Option Default Notes

Site Title

blogname

value entered at install

Shown by most themes and in the feed title.

Tagline

blogdescription

empty

Empty by default; the placeholder text is only a hint.

Site Icon

site_icon

0

Attachment ID. On this screen since 6.5 (before that only in the Customizer; block themes also set it in the Site Editor). At least 512 × 512 pixels.

WordPress Address (URL)

siteurl

install URL

Where the core files live. Locked when WP_SITEURL is defined.

Site Address (URL)

home

install URL

The public address. Locked when WP_HOME is defined.

Administration Email Address

admin_email (pending value in new_admin_email)

install email

A change is not applied until it is confirmed by email (see below).

Membership: Anyone can register

users_can_register

0

Opens wp-login.php?action=register.

New User Default Role

default_role

subscriber

Role given to self-registered users and the preselected role in Users > Add New.

Site Language

WPLANG

absent (English, en_US)

Downloads the language pack when the file system is writable. A WPLANG constant in wp-config.php is obsolete; the screen says so when it finds one.

Timezone

timezone_string, or gmt_offset for a manual UTC offset

UTC+0

Choose a city, not an offset, so daylight saving time is followed.

Date Format

date_format

F j, Y

PHP date characters, used by themes and blocks, not by most admin lists.

Time Format

time_format

g:i a

Week Starts On

start_of_week

1 (Monday)

0 is Sunday.

The two URL fields are the most dangerous fields in the admin. A typo in either one makes the dashboard unreachable, because every redirect then points to the wrong host. The recovery is to fix the value outside the admin: with wp option update home and wp option update siteurl, or by defining WP_HOME and WP_SITEURL in wp-config.php, which overrides the database and locks the fields. Both URLs differ only when WordPress is given its own directory. Changing the domain of an existing site needs a search and replace through the content as well, covered in Importing, Exporting and Migrating.

The administration email is where WordPress sends update results, fatal-error recovery-mode links, new-user and comment-moderation notices. Since 4.9, a change made on the screen is stored in new_admin_email, a hash goes into adminhash, and a confirmation link is mailed to the new address; admin_email changes only when the link is followed. On a site that cannot send mail, the change never completes. There is no WP_ADMIN_EMAIL constant, which one older book suggests; the address can only be changed through the screen, the REST API or WP-CLI. Writing the option directly skips the confirmation:

# Screen-equivalent: stores the pending address and mails a confirmation link
wp eval 'wp_set_current_user( 1 ); update_option( "new_admin_email", "editors@lumenpress.example" );'
wp option get adminhash --format=json   # {"hash":"<hash>","newemail":"editors@lumenpress.example"}

# Direct change without confirmation (for scripted setups and lost mailboxes)
wp option update admin_email editors@lumenpress.example
wp option delete adminhash new_admin_email

The time zone is stored in one of two options. Choosing a city stores timezone_string (for example Europe/Madrid) and leaves gmt_offset alone; choosing a "UTC+1" style entry stores gmt_offset and empties timezone_string. When timezone_string is set, a filter (wp_timezone_override_offset()) recomputes gmt_offset on every read: on the Lumen Press site, wp option get gmt_offset printed 1 while the stored row still held 0. Code should call wp_timezone() or wp_date() instead of reading either option.

Connectors (7.0)

WordPress 7.0 added the AI Client, a provider-neutral PHP API (wp_ai_client_prompt()) that plugins use to send prompts, and the Connectors API that stores the credentials for it. Settings > Connectors is the screen for those credentials. Core bundles no AI provider: the screen lists three featured connectors (Anthropic, Google and OpenAI), and each needs its provider plugin (ai-provider-for-anthropic, ai-provider-for-google, ai-provider-for-openai) before a key can be entered. The screen also lists Akismet, the one non-AI connector core registers, which reuses Akismet’s existing wordpress_api_key option. A notice on the screen offers the separate "AI" plugin, which adds a Settings > AI screen and the editor features (titles, excerpts, alt text, images) that actually use the connectors.

Each connector is a card with its name, description, a link to the provider’s key page, an Install or Activate button when its plugin is missing, and, once the plugin is active, a key field and the connection status. The screen needs JavaScript; without it, it shows only an error notice.

Connector Database option Environment variable and PHP constant

Anthropic

connectors_ai_anthropic_api_key

ANTHROPIC_API_KEY

Google

connectors_ai_google_api_key

GOOGLE_API_KEY

OpenAI

connectors_ai_openai_api_key

OPENAI_API_KEY

Akismet (spam filtering)

wordpress_api_key

constant WPCOM_API_KEY

Other AI providers

connectors_ai_{id}_api_key (hyphens become underscores)

{ID}_API_KEY

How keys behave, as verified on WordPress 7.1.3:

  • Lookup order. An environment variable wins over a PHP constant, which wins over the database option. When the key comes from the environment or a constant, the screen shows its source and does not store anything.

  • Storage. A key typed into the screen is saved in wp_options in plain text. It is masked in the interface and in REST responses (only the last four characters are shown), but it is not encrypted, so it is in every database dump and backup. A Secrets API for stored credentials is expected in WordPress 7.2; until 7.2 ships, it is upcoming and not something to rely on.

  • Registration. The option is registered as a setting only while the provider plugin is active. Without the plugin, /wp/v2/settings does not accept the key at all.

  • Validation. When a key for an AI provider is saved through the REST API, WordPress checks it against the provider. An invalid key is not kept: the option is reset to an empty string and the response returns "".

  • Disabling AI. define( 'WP_AI_SUPPORT', false ); in wp-config.php, or the wp_supports_ai filter returning false, removes the three AI connectors; only Akismet remains on the screen.

The recommended way to provide Lumen Press’s key is an environment variable, so the key never reaches the database or a backup. In the Compose file of the site (the full file is in Local Development Environments):

services:
  web:
    image: wordpress:7.1.3-php8.4-apache
    environment:
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}   # taken from the host's environment or an .env file, never committed

The checks below were run on the Lumen Press site with the Anthropic provider plugin installed. The placeholder key is deliberately invalid, and the application password is the placeholder <app-password>:

$ wp plugin install ai-provider-for-anthropic --activate
$ wp eval 'foreach ( wp_get_connectors() as $id => $c ) { echo $id, " ", $c["authentication"]["setting_name"], "\n"; }'
anthropic connectors_ai_anthropic_api_key
google connectors_ai_google_api_key
openai connectors_ai_openai_api_key
akismet wordpress_api_key

$ curl -s -u "lp_admin:<app-password>" -X POST -H "Content-Type: application/json" \
    -d '{"connectors_ai_anthropic_api_key":"sk-ant-not-a-real-key-1234"}' \
    http://localhost/wp-json/wp/v2/settings | head -c 40
{"connectors_ai_anthropic_api_key":"",

$ wp --exec="define( 'WP_AI_SUPPORT', false );" eval 'echo implode( ",", array_keys( wp_get_connectors() ) );'
akismet

Only administrators can open the screen (manage_options). The AI Client dev note also recommends that plugins expose each AI feature through their own REST endpoint with its own permission check, rather than letting lower roles send arbitrary prompts with the site’s key; the Lumen Press blurb generator follows that pattern in AI Client and Connectors. Plugins that are not AI providers can add their own connector cards with the wp_connectors_init action. None of the older books covers this screen: it did not exist before 7.0.

Writing

Field Option Default Notes

Default Post Category

default_category

1 (Uncategorized)

Term ID given to posts saved without a category. That category cannot be deleted while it is the default.

Default Post Format

default_post_format

0 (Standard)

Only meaningful for themes that support post formats.

Default Link Category

default_link_category

2

Shown only when the legacy Links Manager is enabled (link_manager_enabled).

Post via email: Mail Server, Port, Login Name, Password

mailserver_url, mailserver_port, mailserver_login, mailserver_pass

mail.example.com, 110, login@example.com, empty

POP3 only, checked when wp-mail.php is requested. The password is stored in plain text. Hidden when the enable_post_by_email_configuration filter returns false.

Default Mail Category

default_email_category

1

Update Services

ping_sites

https://rpc.pingomatic.com/

XML-RPC "weblogUpdates.ping" targets, one per line. Shown only when the site is public.

Formatting (emoticons, XHTML nesting)

use_smilies, use_balanceTags

1, 0

Shown only on sites installed before 4.3; new installs never see this section.

There is no setting on this screen to choose between the block editor and the classic editor. One older book describes such a setting; it is added by the Classic Editor plugin, not by core, and core’s only per-type switch is the use_block_editor_for_post_type filter. Post via email is rarely used today: it needs a dedicated, secret POP3 mailbox, anyone who knows the address can publish, and the password sits unencrypted in the database. Lumen Press disables it with add_filter( 'enable_post_by_email_configuration', '__return_false' ); in a must-use plugin. Update Services pings blog directories when a post is published; most of those services no longer exist, and the ping only reveals new URLs early, so many sites empty the list.

Reading

Field Option Default Notes

Your homepage displays

show_on_front

posts

posts or page. Shown only when at least one page exists.

Homepage

page_on_front

0

Page ID used as the front page.

Posts page

page_for_posts

0

Page ID whose URL lists the posts. Its own content and template are ignored.

Number of recent posts shown on archive pages

posts_per_page

10

Called "Blog pages show at most" in older versions and books. Applies to every main archive query, not only the blog.

Number of recent items shown in syndication feeds

posts_per_rss

10

For each post in a feed, include

rss_use_excerpt

0 (full text)

1 sends the excerpt only.

Search engine visibility: Discourage search engines from indexing this site

blog_public

1

The checkbox stores 0 when ticked. See below.

Encoding for pages and feeds

blog_charset

UTF-8

Shown only when the stored charset is not UTF-8. Removed from new installs in 3.5.

Block themes ignore part of this screen. The front page shown is still decided by show_on_front and page_on_front, but the templates (front-page.html, home.html, page.html) decide what is rendered and how many posts a Query Loop block shows unless it is set to inherit the main query. The template hierarchy is covered in Template Hierarchy. The screen warns when the Homepage and the Posts page are the same page, or when either is the Privacy Policy page.

What "Discourage search engines" really does

The checkbox does not hide the site. It sets blog_public to 0, and that value changes five things:

Output blog_public = 1 (default) blog_public = 0

Robots meta tag in <head> (and on wp-login.php), printed by wp_robots()

max-image-preview:large

noindex, nofollow

Virtual /robots.txt from do_robots()

Disallow: /wp-admin/, Allow: /wp-admin/admin-ajax.php and a Sitemap: line

The same two rules, without the Sitemap: line. No Disallow: /.

XML sitemaps at /wp-sitemap.xml (5.5+)

Served

Disabled (404)

Update Services pings (ping_sites)

Sent when a post is published

Not sent; the field is replaced by a notice on the Writing screen

Dashboard

Nothing

"Search engines discouraged" in the At a Glance widget

Until WordPress 5.2, the setting answered /robots.txt with Disallow: /. Version 5.3 replaced that with the noindex meta tag, because a crawler that is forbidden to fetch a page never sees its noindex, and search engines can still list a URL they only know from links. Advice that the checkbox "adds Disallow: / to robots.txt" is outdated. Since 5.7 the meta tag is produced by the Robots API: wp_robots() runs on wp_head, login_head and embed_head, and the wp_robots filter receives an array of directives. The callbacks wp_robots_noindex(), wp_robots_noindex_search(), wp_robots_noindex_embeds() and wp_robots_max_image_preview_large() are attached by default.

Observed on the Lumen Press site with pretty permalinks, first with the default and then after wp option update blog_public 0:

GET /robots.txt  (blog_public = 1)

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php

Sitemap: http://localhost/wp-sitemap.xml

GET /robots.txt  (blog_public = 0)

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php

Practical consequences:

  • The virtual robots.txt exists only when WordPress answers the request. A physical robots.txt file in the web root wins, and with plain permalinks (?p=123) there is no rewrite rule for it: on the Lumen Press site, /robots.txt then redirected to the home page, and the rules were reachable only as /?robots=1.

  • The meta tag only appears in HTML that calls wp_head(). Feeds, REST responses, uploaded PDFs and images carry no directive, so a search engine can still index them.

  • The setting is a request, not access control. A staging site that must stay private needs HTTP authentication or an IP allow list at the web server. A copy of production restored on staging also copies blog_public = 1, which is the usual way staging sites end up in search results.

Lumen Press solves the last point in a must-use plugin that forces the setting off on every non-production environment (WP_ENVIRONMENT_TYPE), adds an X-Robots-Tag header that also covers feeds, and appends two rules to the public robots.txt:

<?php
/**
 * Plugin Name: Lumen Press visibility guard
 * Description: Keeps non-production copies of Lumen Press out of search engines.
 */

// On local, development and staging copies, behave as if "Discourage search engines" were ticked.
if ( 'production' !== wp_get_environment_type() ) {
	add_filter( 'pre_option_blog_public', '__return_zero' );

	// Also send the directive as an HTTP header, which covers feeds and other non-HTML responses.
	add_action(
		'send_headers',
		static function () {
			header( 'X-Robots-Tag: noindex, nofollow', true );
		}
	);
}

// Keep internal search result pages out of crawlers on every environment. Priority -1 runs
// before core adds its "Sitemap:" line at priority 0, so the rules stay in the "User-agent: *" group.
add_filter(
	'robots_txt',
	static function ( $output, $is_public ) {
		if ( $is_public ) {
			$output .= "Disallow: /?s=\n";
			$output .= "Disallow: /search/\n";
		}
		return $output;
	},
	-1,
	2
);

Saved as wp-content/mu-plugins/lumen-visibility.php. On the local copy (WP_ENVIRONMENT_TYPE = local) the site answered with X-Robots-Tag: noindex, nofollow on pages, /robots.txt and /feed/, and with the noindex, nofollow meta tag, even though the stored blog_public was still 1. On a production configuration, the two Disallow lines followed Allow: /wp-admin/admin-ajax.php, before the blank line and the Sitemap: line; at the default priority they would land after the Sitemap: line instead.

The search rules are a crawl-budget choice, not a requirement: core already adds noindex to search result pages through wp_robots_noindex_search(). Sitemaps, structured data and the SEO plugins that replace parts of this output are covered in SEO, Analytics and Privacy.

Discussion

The Discussion screen sets the defaults for comments, pingbacks, moderation and avatars. Its fields map to these options; their meaning and the moderation workflow are explained in Categories, Tags and Comments.

Section Options Defaults

Default post settings

default_pingback_flag, default_ping_status, default_comment_status

1, open, open

Other comment settings

require_name_email, comment_registration, close_comments_for_old_posts, close_comments_days_old, show_comments_cookies_opt_in, thread_comments, thread_comments_depth, page_comments, comments_per_page, default_comments_page, comment_order

1, 0, 0, 14, 1, 1, 5, 0, 50, newest, asc

Email me whenever

comments_notify, moderation_notify, wp_notes_notify

1, 1, 1

Before a comment appears

comment_moderation, comment_previously_approved

0, 1

Comment Moderation / Disallowed Comment Keys

comment_max_links, moderation_keys, disallowed_keys

2, empty, empty

Avatars

show_avatars, avatar_rating, avatar_default

1, G, mystery

The "Anyone posts a note" notification (wp_notes_notify) arrived in 6.9 with Notes, the editorial comments of the block editor. disallowed_keys was called blacklist_keys before 5.5. The two keyword lists are stored with autoload off, unlike the rest of the screen. The "default" settings apply to new posts only; changing them does not touch existing posts, whose comment_status and ping_status columns keep their values.

Media

Field Option Default

Thumbnail size, Crop thumbnail to exact dimensions

thumbnail_size_w, thumbnail_size_h, thumbnail_crop

150, 150, 1

Medium size

medium_size_w, medium_size_h

300, 300

Large size

large_size_w, large_size_h

1024, 1024

Organize my uploads into month- and year-based folders

uploads_use_yearmonth_folders

1

Store uploads in this folder, Full URL path to files

upload_path, upload_url_path

empty

The sizes are maximum dimensions, applied when an image is uploaded; changing them does not resize existing images (wp media regenerate does). Core also creates a medium_large size (medium_large_size_w = 768) and the sizes registered by themes and plugins, none of which appears here. The two upload path fields are shown only when they already hold a non-default value, so they cannot be set from a fresh install’s screen; the supported way to move uploads is the UPLOADS constant. The image_default_* options in the allow list are remembered from the classic media dialog, not edited on the screen. An "Embeds" section appears only when a plugin registers fields for it. Image processing, formats and sizes are covered in Media Library.

Permalinks decide the URL of every post, page and archive. The structure is a string of structure tags stored in permalink_structure; WordPress turns it into the regular expressions of the Rewrite API, stored in the rewrite_rules option.

Choice Stored permalink_structure Example URL

Plain

empty

/?p=123

Day and name

/%year%/%monthnum%/%day%/%postname%/

/2026/10/28/sample-post/

Month and name

/%year%/%monthnum%/%postname%/

/2026/10/sample-post/

Numeric

/archives/%post_id%

/archives/123

Post name

/%postname%/

/sample-post/

Custom Structure

any combination of tags

/news/%category%/%postname%/

The tags offered by the screen are %year%, %monthnum%, %day%, %hour%, %minute%, %second%, %post_id%, %postname%, %category% (nested categories become nested paths) and %author%. Plugins add more through the available_permalink_structure_tags filter. The Optional section sets category_base (default category) and tag_base (default tag). Every structure applies to posts only: pages always use their slug path, and each custom post type sets its own base when it is registered (the Lumen Press lp_book type uses books, so a book lives at /books/<slug>/ whatever the post structure), as shown in Custom Post Types and Taxonomies.

Choosing a structure:

  • /%postname%/ is the common choice and the one Lumen Press uses: short, readable and independent of dates.

  • Dates in URLs make old content look old and change nothing about performance. The long-standing advice to avoid starting with %postname% or %category% for performance reasons stopped applying in 3.3.

  • A structure that begins with /index.php/ ("PATHINFO" permalinks) works without any rewrite module. The screen uses it automatically when it cannot detect URL rewriting.

  • Changing the structure of an established site breaks every old link. Core redirects some old post URLs through wp_old_slug_redirect() and its canonical redirect guesses, but not changed category or tag bases: on the Lumen Press site, /category/uncategorized/ returned 404 once category_base was topics. Plan 301 redirects at the web server before changing a live site.

What "Save Changes" writes

Saving the screen updates the options and calls flush_rewrite_rules(), which rebuilds rewrite_rules and, on Apache, writes the rewrite block into .htaccess in the site root through save_mod_rewrite_rules(). WordPress only edits the lines between its own # BEGIN WordPress and # END WordPress markers; rules outside the markers are kept. When the file or the directory is not writable, the screen prints the rules to paste by hand. With the Lumen Press settings, the generated block was:

# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

The block is the same for every structure: all non-file requests go to index.php, and WordPress matches the URL against rewrite_rules in PHP. That is why a new structure needs no new .htaccess lines, and why "404 on every page except the home page" after a migration usually means the block is missing or AllowOverride is off for the directory. The HTTP_AUTHORIZATION line passes the Authorization header to PHP, which application passwords need. The same file is managed on IIS as web.config. On nginx, Caddy and FrankenPHP (detected from SERVER_SOFTWARE), the screen writes nothing and shows no rules; the server configuration needs the equivalent once, for nginx try_files $uri $uri/ /index.php?$args;, as described in Web Servers: Apache and nginx. Older books show Apache 2.2 Order allow,deny blocks next to these rules; Apache 2.4 uses Require.

The same settings from WP-CLI. wp rewrite structure stores the structure and flushes the rules, but WP-CLI only writes .htaccess when called with --hard and told that mod_rewrite is loaded, because it cannot inspect the web server from the command line:

$ wp rewrite structure '/%postname%/' --category-base=topics --tag-base=subjects
Success: Rewrite structure set.
Success: Rewrite rules flushed.

$ wp rewrite flush --hard
Warning: Regenerating a .htaccess file requires special configuration. See usage docs.
Success: Rewrite rules flushed.

$ printf 'apache_modules:\n  - mod_rewrite\n' > wp-cli.yml
$ wp rewrite flush --hard
Success: Rewrite rules flushed.

The Rewrite API behind this screen (custom rules, endpoints, add_rewrite_rule(), when to flush) is covered in Rewrite API and Permalinks.

Privacy

The Privacy screen (since 4.9.6, with the GDPR tools) does one thing: it chooses the Privacy Policy page, stored as a page ID in wp_page_for_privacy_policy. The installer already creates a draft page titled "Privacy Policy" with suggested text (ID 3 on a fresh install) and points the option at it. The screen offers to select an existing page or to create a new one, and links to the Policy Guide (Settings > Privacy > Policy Guide tab), where core, themes and plugins add suggested paragraphs through wp_add_privacy_policy_content().

Effect of the setting Detail

get_privacy_policy_url() and the_privacy_policy_link()

Return the page’s URL and a link, used by wp-login.php, the registration form and themes. They return nothing while the page is a draft.

Comment form consent and the cookie checkbox

Themes can link the policy next to the consent field.

Editing the page

Requires manage_privacy_options on top of edit_pages; the editor shows a notice with a link to the guide.

Reading screen warnings

The page must not also be the Homepage or the Posts page.

The screen only stores a page ID. The text is the site owner’s legal responsibility, and the draft created at install is a template, not a policy. The personal data export and erasure tools live under Tools, and plugins hook into them as shown in Privacy and Personal Data. Cookie consent and analytics are covered in SEO, Analytics and Privacy.

Lumen Press: all settings as a script

Clicking through eight screens on every new environment is error-prone. Lumen Press keeps its baseline settings in a shell script run once after wp core install (Installation):

#!/bin/sh
# Lumen Press: baseline settings, run once after "wp core install".
set -e

# General
wp option update blogname 'Lumen Press'
wp option update blogdescription 'Independent books since 1998'
wp option update timezone_string 'Europe/Madrid'
wp option update date_format 'j F Y'
wp option update time_format 'H:i'
wp option update start_of_week 1
wp option update users_can_register 0
wp option update default_role subscriber

# Writing
wp option update default_post_format 0

# Reading: static front page plus a posts page
home_id=$(wp post create --post_type=page --post_status=publish --post_title='Home' --porcelain)
news_id=$(wp post create --post_type=page --post_status=publish --post_title='News' --porcelain)
wp option update show_on_front page
wp option update page_on_front "$home_id"
wp option update page_for_posts "$news_id"
wp option update posts_per_page 12
wp option update rss_use_excerpt 1
wp option update blog_public 1

# Discussion
wp option update default_pingback_flag 0
wp option update default_ping_status closed
wp option update close_comments_for_old_posts 1
wp option update close_comments_days_old 30
wp option update comment_previously_approved 1

# Media
wp option update large_size_w 1200
wp option update large_size_h 1200

# Permalinks
wp rewrite structure '/%postname%/' --category-base=topics --tag-base=subjects

# Privacy: publish the draft policy page created by the installer
policy_id=$(wp option get wp_page_for_privacy_policy)
wp post update "$policy_id" --post_status=publish

After the script, wp option get returned the values above (the Home and News pages got IDs 5 and 6), and /, /news/, /topics/uncategorized/, /privacy-policy/ and /robots.txt all answered 200. Writing options directly skips the screen’s side effects: the admin email confirmation, the .htaccess rewrite (unless wp rewrite flush --hard is configured as shown above), and the sanitizing done by options.php for values typed by hand. The site language is set with wp language core install es_ES --activate or wp site switch-language, which also download the language files, rather than by writing WPLANG.

Pitfalls

  • Locked URL fields. Greyed-out WordPress Address and Site Address fields mean WP_SITEURL and WP_HOME are defined in wp-config.php. Edit them there.

  • Settings that "do not save". A page cache or an unflushed persistent object cache shows old values, or a plugin forces a value with a pre_option_{option} filter, as the Lumen Press visibility guard does on purpose.

  • Static front page with a block theme. A home.html template is used for the Posts page, and a front-page.html template, when present, renders the front page whichever Homepage option is chosen.

  • A "discouraged" site still listed. Pages indexed before the box was ticked stay listed until a crawler revisits them and sees noindex; a hand-written Disallow: / in a physical robots.txt prevents that revisit.