Configuration
Every OpenTrust settings field across General, Contact, AI Chat, and Import & Export.
All settings live at OpenTrust → Settings. Most of them are stored as a single serialized array under the opentrust_settings option, so a deactivate-then-reactivate cycle preserves your configuration. AI provider keys are stored separately in opentrust_provider_keys and encrypted at rest.
The settings page is split into four tabs.
General
Branding and the public surface of your trust center.
Endpoint
| Field | Default | Description |
|---|---|---|
| Endpoint slug | trust-center | The URL path your trust center lives at. Saves trigger an automatic rewrite-rule flush on the next request. Works with any non-empty string a /^[a-z0-9-]+$/ pattern allows. |
| Page title | Trust Center | The big H1 in the hero. |
| Tagline | empty | Optional one-line strapline below the title. |
Branding
| Field | Default | Description |
|---|---|---|
| Company name | empty | Used in the hero, the contact block, and every email link if you have one. Leaving it blank falls back to your Site Title at runtime. |
| Logo | none | Top-left of the trust center. PNG, JPG, WebP, or SVG. SVG must already exist in your media library; OpenTrust does not enable SVG uploads. |
| AI avatar | none | Optional avatar shown in the AI chat header. Square, 64×64 or larger. |
| Accent colour | #3b82f6 | Brand colour for headings, buttons, and section dividers. OpenTrust clamps lightness in HSL space until the colour clears 4.5:1 on white. The settings screen renders a live "Low contrast" warning while you pick. |
| Force exact accent | off | Override the WCAG clamp and use the exact hex you picked. Off by default. |
Turning on Force exact accent can produce inaccessible buttons and links. Only do this if your brand guidelines explicitly require an exact tint and you accept the contrast hit.
Sections
Each section toggle hides or shows that block on /trust-center/. All on by default.
| Section | Renders when |
|---|---|
| Hero | Always (toggle hides the title and tagline). |
| Certifications | At least one published ot_certification. |
| Policies | At least one published ot_policy. |
| Subprocessors | At least one published ot_subprocessor. |
| Data practices | At least one published ot_data_practice. |
| FAQ | At least one published ot_faq. |
| Contact | Any contact field below is filled. |
Contact
Optional. Every field is independent; the contact block renders only the rows you fill.
| Field | Description |
|---|---|
| Company description | Two or three sentences shown above the contact rows. |
| DPO name + email | Data Protection Officer. |
| Security contact email | For coordinated disclosure or security questions. Often security@yourdomain.com. |
| Contact form URL | Link to a wider contact form, if you want one. |
| Mailing address | Multiline string, rendered with line breaks preserved. |
| PGP key URL | Public key URL for security disclosures. |
| Company registration | KvK / Companies House number, etc. |
| VAT / Tax ID | Optional but useful for procurement vendor onboarding. |
AI Chat
The AI Chat tab gates whether the chat is enabled, which provider answers, and how visitors are rate-limited. Every field is documented in detail in AI Chat. Quick reference:
| Field | Default | Description |
|---|---|---|
| Provider | Anthropic | Use Anthropic. Its native Citations API is the only way to get verifiable, source-anchored citations. OpenAI and OpenRouter are supported but not recommended. See AI Chat / Choose a provider. |
| API key | none | Encrypted at rest with libsodium secretbox, salted from wp_salt('auth'). Required to enable the chat. |
| Model | provider default | Populated by clicking Refresh model list after the key is saved. |
| Daily token budget | 500000 | Hard daily ceiling. Set to 0 for no daily cap (still bound by monthly). |
| Monthly token budget | 10000000 | Hard monthly ceiling. Set to 0 for no cap (admin opt-out). |
| Per-IP rate limit | 10 per 60s | Sliding window. Range 0 to 1000. |
| Per-session rate limit | 50 per hour | Sliding window. Range 0 to 10000. |
| Max message length | 1000 characters | Range 100 to 4000. Chars over the cap are rejected client-side. |
| Show model attribution | off | Append a Powered by {model} footer to chat answers. |
| Logging | on | Records hashed-only entries to wp_opentrust_chat_log. |
| Auto-summarize | on | Generate per-policy 2-3 sentence routing summaries on save (via single-event cron). |
| Cloudflare Turnstile site key | empty | Optional bot defence, see below. |
| Cloudflare Turnstile secret key | empty | Stored encrypted alongside the AI key. |
| Contact CTA URL | empty | Where the chat redirects visitors when it refuses to answer or hits the budget cap. Falls back to your contact email or contact form URL. |
Setting both daily and monthly token budgets to 0 removes every cost ceiling. The per-IP and per-session rate limits still apply, but the AI provider bill becomes uncapped.
Import & Export
Selective JSON-first archives for moving content and settings between environments (staging to production, dev to staging, etc.). Two artifact types:
Content ZIP
Bundles every ot_policy, ot_certification, ot_subprocessor, ot_data_practice, and ot_faq post with full meta. PDFs, badges, and logo attachments referenced by content are included as media/{sha256}.{ext} files in the archive. Cross-references (FAQ → related policy, policy → PDF attachment) are exported as UUID and SHA-256 references and remapped on import.
Settings ZIP
Bundles opentrust_settings plus the logo and AI-avatar attachments referenced by it. Encrypted secrets (AI provider keys, Turnstile secret) are excluded by design and must be re-entered on the destination.
Conflict strategies
When the importer finds a record with the same UUID or slug as an incoming record:
| Strategy | Behaviour |
|---|---|
skip (default) | Existing record wins. The incoming record is dropped. |
overwrite | Existing record is overwritten with incoming meta. Post ID and timestamps are preserved. |
create_new | Incoming record is inserted with a suffixed slug and a fresh UUID. Useful for cloning. |
What is never exported
| Excluded | Why |
|---|---|
opentrust_provider_keys | Encrypted secrets do not survive AUTH_KEY rotation across sites. Re-enter on the destination. |
turnstile_secret_key | Same reason. |
opentrust_site_salt | Per-site, regenerated on demand. |
ai_enabled, ai_provider, ai_model_list_cached_at | Operational state, not configuration. |
wp_opentrust_chat_log | Visitor-side data. Should not migrate environments. |
Transients and opentrust_cache_version | Rebuilt on the destination. |
Validation
The importer hard-rejects archives whose opentrust_version major version does not match the running plugin, and rejects schema-version mismatches. Beyond that, integrity is the admin's responsibility. The import panel surfaces an "Only upload your own exports" warning before applying.