Install guide

Two things need to be live on your site: the notice your visitors see, and a small public file that declares your AI use (yoursite.com/.well-known/ai-disclosure.json). The snippet tag is pasted once, is identical on every page, and your declaration decides which notices appear where. Pick your platform below; most take about ten minutes.

1 · Show the notices

Banner and AI labels your visitors see on the page.

2 · Publish your declaration

ai-disclosure.json, a public file readable from your own domain.

You are done when

the checker shows Level 2 · Rendered.

Pick your platform

WordPress

  1. Install the plugin

    In your WordPress admin: Plugins → Add New → Upload Plugin, choose the file you downloaded below, then click Activate.

    Download the AIDisclose plugin (.zip)

  2. Let it do both jobs

    The plugin shows the notices and publishes your declaration file automatically. Mark AI content on any post or image with its "AI content" toggle. No code edits.

  3. Verify

    Done when the checker shows Level 2 · Rendered.

    Run the checker

Verify

Run the checker. It confirms three things: your declaration file is valid, the snippet is running, and the notices actually appear on the page. (For engineers: checks C1, C3, and C4 to C6.)

Run the checker

If your site blocks our checker (AIDiscloseBot)

Scans and evidence captures come from AIDiscloseBot/1.0. It reads public pages only: it never signs in, never submits forms, and obeys robots.txt. If your robots.txt or bot protection blocks unknown crawlers, allow it explicitly:

robots.txt
User-agent: AIDiscloseBot
Allow: /

Is allowing it a risk? No. A robots.txt allow grants no access. It only tells polite bots they may read pages that are already public. Anyone can fake a User-Agent string, but a faker gains nothing your public pages don't already give them.

If you gate traffic with a WAF or bot manager, never allowlist on User-Agent alone. Pair it with source verification. We publish our crawler identity, and the egress IP ranges as they are provisioned, at aidisclose.io/bot.json.

Run the checker

Advanced

Theming with CSS variables, custom copy, single-page-app setup, and the full option reference are in the snippet reference.

Lock the script to an exact version (SRI)

An integrity hash in the script tag makes the browser refuse to run a modified file. Pin the versioned URL and generate the hash from the exact file you deploy:

shell
curl -sO https://cdn.aidisclose.io/v1/aidisclose.js
openssl dgst -sha384 -binary aidisclose.js | openssl base64 -A
Serve the file yourself (nginx / Apache)

For servers you control, serve the downloaded ai-disclosure.json directly:

nginx
location = /.well-known/ai-disclosure.json {
  alias /var/www/site/ai-disclosure.json;
  default_type application/json;
  add_header Cache-Control "max-age=3600";
}
Apache
Alias "/.well-known/ai-disclosure.json" "/var/www/site/ai-disclosure.json"
<Files "ai-disclosure.json">
  ForceType application/json
</Files>
Serve the dashboard-hosted file from your own domain

Your server forwards requests for that one address to us: you edit the file in the dashboard, and it still serves from your domain. The dashboard shows these pre-filled with your site key.

nginx
location = /.well-known/ai-disclosure.json {
  proxy_pass https://cdn.aidisclose.io/v1/hosted-manifest/YOUR_SITE_KEY;
  proxy_set_header Host cdn.aidisclose.io;
  proxy_ssl_server_name on;
}
Cloudflare Worker
export default {
  async fetch(request) {
    const url = new URL(request.url);
    if (url.pathname === "/.well-known/ai-disclosure.json") {
      return fetch("https://cdn.aidisclose.io/v1/hosted-manifest/YOUR_SITE_KEY");
    }
    return fetch(request);
  }
};
Single-page apps and static hosts

Frameworks that rewrite every route to index.html, and some static hosts, intercept /.well-known/ai-disclosure.json and return your app's HTML with a 200 status. The file looks committed, but the checker reads HTML instead of the manifest. Two fixes: exclude /.well-known/ from the catch-all rewrite so the static file is served with the application/json type, or add data-aidisclose="YOUR_SITE_KEY" to the script tag to load the AIDisclose-hosted manifest and skip serving the file entirely.

netlify.toml / vercel.json
# netlify.toml: serve the real file before the SPA fallback
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
  force = false   # a real file at the path wins over this fallback

# vercel.json: rewrite everything EXCEPT /.well-known to the app
{ "rewrites": [
  { "source": "/((?!\.well-known/).*)", "destination": "/index.html" }
] }