=== TransparAI: AI Image Detection, EU AI Act Labeling & SEO ===
Contributors: contexlabs
Tags: eu ai act, ai transparency, c2pa, ai label, seo
Requires at least: 6.2
Tested up to: 7.1
Stable tag: 1.0.3
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Detect AI images via C2PA Content Credentials and IPTC, add an AI badge, EU AI Act Article 50 disclosure and SEO-ready structured data.

== Description ==

TransparAI is the AI transparency and AI compliance plugin for WordPress: it detects AI-generated images in your media library, labels them with a visible AI badge, writes the machine-readable AI disclosure (the IPTC digital source type) into the image files, and adds the two other disclosures Article 50 of the EU AI Act asks for, the note on AI-written text and the notice in front of a chatbot. Detection, labeling, structured data for SEO, audit trail and REST API, all on your own server, without a single external request.

**Automatic AI image detection**

Most AI image generators leave traces in their files, and TransparAI reads all of the common ones: C2PA manifests (Content Credentials) from OpenAI (ChatGPT, DALL-E, GPT-Image), Adobe Firefly, Google Gemini including Nano Banana, and Bing Image Creator; the IPTC digital source type in XMP as written by Midjourney and a growing number of tools; generation parameters in PNG chunks from Stable Diffusion (AUTOMATIC1111), ComfyUI, NovelAI and InvokeAI; EXIF and XMP signatures of Flux, Leonardo.Ai, Ideogram, Recraft, Seedream and Photoshop Generative Fill; JPEG comment markers, C2PA in MP4 video and AI declarations in MP3 audio.

Detection parses the real file containers (JPEG segments, PNG chunks, RIFF, MP4 boxes, ID3 frames) and matches only inside metadata blocks, never with a blind text search over raw bytes. Cameras from Leica, Sony and Nikon embed Content Credentials into real photos too, so a C2PA manifest alone never auto-labels anything here. Findings carry a confidence level: explicit AI declarations are labeled automatically, strong but informal signals land in a review queue where you confirm or dismiss them, single or in bulk, right in the media library. New uploads are checked on arrival, the existing library in a batched, pausable scan. Media generated by AI plugins on your own site (AI Engine, AI Power, Elementor AI, WordPress AI) is labeled at the source.

**The visible AI label**

A configurable AI badge marks labeled media in the front end: overlay or caption line, four positions, three sizes, dark, light, outline or icon-only, optional generator name, optional alt text note for screen readers, optional start date so older content is not badged retroactively. It renders server-side, so it survives page caching, and it works with the block editor, the classic editor, template images, widgets, Elementor free and Pro including Theme Builder, WPBakery Page Builder, and WooCommerce: the badge follows variation swaps, reappears inside the zoom and PhotoSwipe lightbox and the core image lightbox, and stays out of WooCommerce e-mails. Themes that stack hover layers over images are handled by a guard that checks the real paint order and moves a covered badge to a free corner or below the image. Per-image overrides and CSS utility classes give theme builders full control; an optional script also labels images printed without an attachment ID and CSS backgrounds. Page-cache plugins (WP Rocket, LiteSpeed, W3 Total Cache, WP Super Cache and more) are told to refresh whenever a label changes.

**Machine-readable AI labeling, structured data and SEO**

For labeled files TransparAI writes the IPTC digital source type (trainedAlgorithmicMedia, or compositeWithTrainedAlgorithmicMedia for AI-edited media) as XMP into JPEG, PNG, WebP and AVIF, every size variant included. Google documents this field and can show an "AI-generated" label in Google Image Search, so the disclosure travels with the image wherever it is indexed. Each page additionally carries Schema.org JSON-LD structured data (ImageObject, VideoObject, AudioObject and an Article node for AI-written posts) with digitalSourceType both as the Schema.org enumeration and as the IPTC vocabulary URI, so search engines and AI crawlers get the declaration without opening a file. All of it is server-rendered with no extra HTTP request and no layout shift, so the SEO signals arrive without a Core Web Vitals cost. The same declarations serve GEO (generative engine optimization): AI search and answer engines such as Google AI Overviews, ChatGPT search and Perplexity read structured data and provenance signals when they decide what to cite, and a page that states the origin of its images and texts in machine-readable form gives them exactly that. Content Credentials in the files, IPTC in XMP, Schema.org in the page, dc:description in the feed: one truth in four places search engines, AI crawlers and browsers already understand. Existing metadata is merged, not replaced; unlabeling removes exactly what the plugin wrote; writes are atomic and validated. Because image optimizers and thumbnail regeneration strip metadata, every labeled file is fingerprinted and an hourly sweep restores missing declarations.

**Camera photos and human work**

Not every declaration says "AI". Any media file can be declared as a camera photo (digitalCapture) or as human digital work (digitalCreation), from the attachment details, in bulk, or with WP-CLI. The declaration ends any AI label or pending detection, appears in the structured data, and is written into the file, but only where no other digital source type exists: a camera's own declaration stays untouched. A "Human made" badge is optional and off by default.

**AI-written text: disclosure levels per post**

Every post, page and public custom post type carries an AI level for its text: no AI used, AI-assisted, AI-generated, or AI-generated and reviewed by a person. Set it in the block editor sidebar, the classic meta box, Quick Edit or Bulk Edit; the post list gets a sortable column and a filter. AI levels show a configurable note before or after the content, the "AI notice" block and the `[transparai_notice]` shortcode place it by hand, and reviewed texts record the reviewer, the date and a fingerprint of the text and its images, so a later edit shows as "changed since review". The note can go into excerpts and RSS feed items, including a machine-readable dc:description element.

**Chatbot disclosure**

Visitors must know when they talk to an AI system. TransparAI puts that notice into the first message of the bot for AI Engine, next to the chat launcher for every other widget, or as a line at the end of each page. Your answer decides whether it appears and who answers in the chat; the plugin recognizes more than 40 chat and chatbot vendors locally (plugins, theme snippets, registered scripts, your own browser as administrator) and tells you what it found, but never switches the notice on from a finding alone, because a live chat with a person behind it is not an AI system.

**Audit trail, REST API, WP-CLI**

Every label, review decision, declaration and repair is recorded per file with time, previous state, trigger and the editor's name, plus a site log of settings changes, scans, sweeps and bulk actions. Export the whole library as a CSV audit list, or open the print view with a document hash over the facts, the guidance basis and the stated limitations, ready for print-to-PDF. A REST API under `transparai/v1` exposes rows, per-file detail, every action and the report for headless setups and agency tooling; nothing in it is public. WP-CLI covers scanning, labeling, declaring and auditing (`wp transparai scan`, `status --format=csv`, `verify-meta --repair`). Other plugins can label media through `do_action( 'transparai_mark_ai', $attachment_id, 'My Generator' )`, detection rules are extensible via filters, WPML and Polylang are configured, and uninstalling cleans up across a multisite network on request.

**Privacy by design**

The plugin runs entirely on your server: no accounts, no telemetry, no external requests. The only HTTP request it can make is the optional delivery check, which asks your own site for one image to see whether your CDN strips the declaration. The interface is available in English, German, French, Spanish, Italian and Dutch. Please also read the Disclaimer section.

Contact: TransparAI@cms-admins.de

== Installation ==

1. Install the plugin from the WordPress plugin directory (Plugins, Add New, search for "TransparAI") or upload the ZIP, then activate it. The activation opens **Media, TransparAI** with a three-step setup: scan the library, choose the badge look with a live preview, decide whether declarations are written into the files. Every step can be undone, and "Not now" hides the card for you until you open it again.
2. New uploads are checked automatically from now on.
3. Click **Scan new/unscanned media** (or "Scan now" in the setup) to go through your existing library in small batches, pausable at any time.
4. Clear declarations are labeled right away; strong signals land in the review queue. Follow the **Open review queue** link and confirm or dismiss each item, single or in bulk. A camera photo with Content Credentials shows up here on purpose; dismiss it once and it stays dismissed. Media you have already decided on yourself is reported as skipped in the scan summary and is never overruled.
5. Adjust the badge under **Visible badge**, and if your theme prints images without an attachment ID (ACF URL fields, sliders) or uses CSS backgrounds, enable the extra option under **Extras**.
6. Single image sitting awkwardly? Open its attachment details and pick a **Badge position** there: another corner, a caption line below the image, or no visible badge for that one image.

Everything else runs on its own: labeled files get the IPTC digital source type written into the file (verify with `exiftool -XMP-iptcExt:DigitalSourceType image.jpg`), and the hourly sweep restores metadata that optimizers strip.

== Frequently Asked Questions ==

= Can the plugin detect every AI image? =

No, and no plugin can. Detection relies on metadata that generators embed. Images whose metadata was stripped (social media re-uploads, screenshots, clipboard pastes) carry no signals. Invisible pixel watermarks such as Google SynthID can only be verified by the vendor's own service; TransparAI does not pretend otherwise. Detected metadata is an indication, not cryptographic proof. That is exactly why the review queue exists.

= Which AI image generators are recognized? =

Anything that leaves a standard marking in the file. In practice that covers ChatGPT and DALL-E, GPT-Image, Google Gemini including Nano Banana output, Adobe Firefly and Photoshop Generative Fill, Bing Image Creator, Midjourney, Stable Diffusion (AUTOMATIC1111, ComfyUI, InvokeAI, SwarmUI, Fooocus), NovelAI, Flux by Black Forest Labs, Leonardo.Ai, Ideogram, Recraft and Seedream, plus every tool that writes a C2PA manifest or the IPTC digital source type, which is the direction the whole industry is moving in. New signatures can be added with a filter, no code fork needed. TransparAI is an independent plugin and is not affiliated with any of these vendors.

= Does the plugin make my site compliant with the EU AI Act? =

It gives you the technical building blocks Article 50 asks for: a visible disclosure and a machine-readable marking. Whether and how the EU AI Act or any other law applies to your site, and whether your specific setup satisfies it, is a legal question only you (or your lawyer) can answer. See the Disclaimer section.

= Is this legal advice? =

No. TransparAI is a technical tool, not legal advice, and using it creates no guarantee of compliance with any regulation. See the Disclaimer section.

= Does the plugin change my image files? =

Only when a file is labeled and the metadata option is enabled. The plugin then writes a small XMP block into the JPEG, PNG, WebP or AVIF file and its size variants. The image pixels are untouched. Files are replaced atomically and validated first. Unlabeling removes exactly the metadata this plugin wrote; foreign metadata is never touched.

= Where can I see what was written into a file? =

Open the attachment details and click "Show file metadata". It lists every file of that attachment with its state (declaration present, missing, or a format that cannot carry one), the digital source type currently declared, the detection evidence in full, the recorded history and the raw XMP packet of the main file. Nothing is written while you look; it is a read of the files as they are on disk right now.

= Does the marking survive my CDN? =

Not always, and that is worth checking. Image optimizers at the edge, Cloudflare Polish and Jetpack Photon among them, re-encode images while delivering them and drop every metadata block in the process. The file on your server stays perfect while visitors and search engines receive a bare image, and nothing in WordPress shows it. Enable the delivery check in the settings, then press "Check delivery" on a labeled image: the plugin fetches that image from your own public URL and tells you whether the declaration arrived. If it did not, the fix is in your CDN configuration (keep metadata, or exclude labeled images from re-encoding), not in this plugin.

= Does AI labeling affect my SEO and GEO? =

It gives search engines exactly the signals they document. Google reads the IPTC digital source type that TransparAI writes into the image files and can show an "AI-generated" label in Image Search; the Schema.org JSON-LD in the page carries the same declaration for search engines and AI crawlers that never open the file. Everything is rendered server-side, adds no request and shifts no layout, so there is no Core Web Vitals cost. Whether and how a search engine treats labeled images in ranking is its decision, not something a plugin can promise; what the labeling avoids is the opposite risk, an undisclosed AI image that a platform or a competitor points out later. For GEO, generative engine optimization, the same structured data tells AI search and answer engines where your images and texts come from, which is part of what they weigh when they cite a source.

= Does the plugin detect my chatbot? =

It recognizes more than 40 chat and chatbot vendors by their plugin directory, their script hosts, their JavaScript globals and their widget markup, entirely locally. The finding shows on the settings page with a hint whether a bot or people usually answer there. You decide whether the notice appears; the plugin never switches it on from a finding alone, because a live chat with a person behind it is not an AI system.

= Can I also label AI-written text? =

Yes. Every post and page has an AI level in the editor sidebar (no AI used, AI-assisted, AI-generated, AI-generated and reviewed), also available in Quick Edit and Bulk Edit of the post list. AI levels show a configurable note ahead of or after the content; the "AI notice" block and the `[transparai_notice]` shortcode place it by hand instead. Reviewed texts record the reviewer, the date and a fingerprint of the content, so a later edit is visible as "changed since review". Optionally the note goes into excerpts and RSS feed items too. There is also an optional site-wide note at the end of pages that contain labeled media.

= Why was a real camera photo put into the review queue? =

Modern cameras embed C2PA Content Credentials into real photos. A C2PA manifest alone therefore never auto-labels. It lands in the review queue unless the manifest declares an AI source. Dismiss it with one click; dismissed files are not queued again.

= Which page builders and editors are supported? =

The visible badge covers the block editor (every image-bearing block incl. cover, media-text, galleries, inline images in text, video and audio), the classic editor, template images, text widgets, Elementor free and Pro (image, galleries, carousels, slides, image box, hotspot, flip box, call to action, posts, Theme Builder) and WPBakery Page Builder (single images, galleries, carousels, row and column backgrounds, parallax, grids). Inside the builders' own editing screens badges are deliberately not injected. For images a theme prints without an attachment ID (ACF URL or array fields) enable the option under Extras: a small script matches those images and CSS backgrounds against your labeled files. The machine-readable XMP labeling is independent of any builder and always works.

= My theme puts overlays on images; does the badge disappear under them? =

Usually not, and never silently. Badges sit above typical theme layers (hover effects, zoom icons, sale badges), and a small script additionally checks the real paint order: a badge that is still covered is raised, moved to a free corner or, as the last resort, shown as a caption line below the image (this guard can be turned off under Visible badge, Extras). For manual control, give any container one of the utility classes `trai-badge-top-left`, `trai-badge-top-right`, `trai-badge-bottom-left`, `trai-badge-bottom-right`, `trai-badge-below` or `trai-badge-hidden`, or pick a position for a single image in its attachment details ("Badge position"). Both ways switch the guard off for those badges, and `trai-badge-manual` does the same without changing the position, for the rare case where the guard misjudges your layout. Hiding the visible badge of one image never touches the machine-readable file metadata or the structured data in the page; that part of the disclosure stays intact.

= Does the plugin phone home? =

No. There are no external requests of any kind. All detection happens by reading file bytes locally on your server.

= What happens when I uninstall the plugin? =

By default your labels stay in the database (reinstalling restores them) and metadata already written stays in the files. If you prefer a full cleanup, enable "Delete all plugin data" in the settings before uninstalling. Unlabel files first if you also want the in-file metadata removed.

= Can I label media programmatically? =

Yes. The meta key `_transparai_ai` is registered for the REST API, WP-CLI commands cover bulk work, and other plugins can call `do_action( 'transparai_mark_ai', $attachment_id, 'Generator name' )`.

= Where do I get help? =

Post in the support forum here on wordpress.org, or write to TransparAI@cms-admins.de. The plugin is built and maintained by Patrick Schlesinger (cms-admins.de).

== For developers ==
Everything below is stable API surface; hooks and options use the `transparai_` prefix, meta keys `_transparai_`. The full developer reference with every shape and example lives in the GitHub README: https://github.com/cmsadmins/TransparAI

**Attachment meta** (REST-exposed, `upload_files`): `_transparai_ai` (`'1'` = confirmed AI label), `_transparai_type` (`generated`|`composite`), `_transparai_source`, `_transparai_generator`, `_transparai_confidence`, `_transparai_detected` (pending review), `_transparai_human` (`digitalCapture`|`digitalCreation`, mutually exclusive with the label), `_transparai_badge_pos`, `_transparai_history` (last fifty events with time, trigger, previous state and editor name), `_transparai_delivery`.

**Post meta** (REST-exposed, `edit_post`): `_transparai_content_ai` (`none`|`assisted`|`generated`|`generated_reviewed`), `_transparai_content_responsible`, `_transparai_content_review` (plugin-written stamp with reviewer, date and content fingerprint; never writable through REST).

**Hooks:** `do_action( 'transparai_mark_ai', $attachment_id, 'My Generator' )` labels media from your code; filters `transparai_signatures`, `transparai_detection_result`, `transparai_badge_html`, `transparai_badge_wrap_classes`, `transparai_notice_text`, `transparai_notice_html`, `transparai_chatbot_vendors`, `transparai_chatbot_notice`.

**Shortcode and block:** `[transparai_notice type="content|media" style="block|inline" text="" id=""]` and the "AI notice" block render only what is declared; a placed note silences the automatic one.

**REST API** (`/wp-json/transparai/v1/`, authenticated, `upload_files`, writes need `edit_post`, the report `manage_options`): `GET /media`, `GET|POST /media/{id}` (`action=flag|unflag|confirm|dismiss|human_capture|human_creation|human_remove`), `POST /media/{id}/scan`, `GET /report` with `document_hash`.

**WP-CLI** (`wp transparai`): `scan [--all] [--dry-run]`, `flag`, `unflag`, `human [--type=capture|creation] [--remove]`, `status [--status=...] [--format=csv|json|...]`, `write-meta --yes`, `verify-meta [--repair]`, `verify-delivery`.

**Theme control:** container classes `trai-badge-top-left`, `trai-badge-top-right`, `trai-badge-bottom-left`, `trai-badge-bottom-right`, `trai-badge-below`, `trai-badge-hidden`, `trai-badge-manual`; stacking via the CSS custom property `--trai-badge-z`. Images printed through `wp_get_attachment_image()` or with a `wp-image-{ID}` class are badged server-side and page-cache safe.

== External services ==
None. The plugin makes no request to any external service and never sends media or site data anywhere. The only HTTP request it can make is the optional delivery check, which fetches one image from your own site to see whether a CDN strips the declaration; it is off by default, runs only on click, and stops if the image is served from another host.

== Privacy ==
TransparAI processes media files locally on your server and stores its results in the WordPress database (post meta and a few options). The per-file history records the user ID and display name of whoever labeled, confirmed, declared or dismissed a file (last fifty events), a site log keeps the last 200 administrative events, and a post marked as reviewed stores the reviewer's name and user ID, which is shown publicly only when you enable it. Everything is removed on uninstall with data removal enabled. The plugin collects, transmits and shares nothing and sets no cookies.

== Disclaimer ==
TransparAI is a technical tool, not legal advice, and is provided "as is" without warranty of any kind, to the extent permitted by law (GNU GPL v2, sections 11 and 12). The author makes no representation that using it makes your site compliant with the EU AI Act, the Digital Services Act or any other law; legal obligations depend on your situation and remain your responsibility as the site operator. Detection is based on metadata embedded by generators: stripped files carry no signals, and detected metadata is an indication, not proof. No function is guaranteed to run without error in every environment. You use this plugin at your own risk; to the extent permitted by law, the author accepts no liability for damages arising from its use.

== Screenshots ==

1. Media library grid with AI badges, a review state and bulk labeling
2. Attachment details: label checkbox, detection evidence, review actions and the file inspection with its raw XMP packet
3. Settings page with library statistics, the batched scan and the audit export
4. Front-end badge on a labeled image

== Changelog ==

= 1.0.3 =
* AI-written text: a disclosure level per post (no AI, AI-assisted, AI-generated, AI-generated and reviewed) in the block editor sidebar, the classic meta box, Quick Edit and Bulk Edit, with a sortable list column and filter. Reviewed texts record reviewer, date and a content fingerprint that flags later edits. New "AI notice" block and `[transparai_notice]` shortcode; the note can go into excerpts and RSS feeds (dc:description).
* Camera photos and human work: media can be declared as digitalCapture or digitalCreation, in the details, in bulk or via `wp transparai human`; written into files that carry no other digital source type, shown in the structured data, optional "Human made" badge.
* WooCommerce: the badge follows variation swaps, is re-created inside the zoom and PhotoSwipe lightbox and the core image lightbox, stays out of WooCommerce e-mails; HPOS compatibility declared.
* REST API `transparai/v1` (media rows, per-file detail, actions, re-check, report), authenticated only.
* Audit trail: fifty events per file with previous state, trigger and editor name; site log; CSV export with history, BOM and formula guard; print view with document hash, guidance basis and limitations; paginated exports.
* First-run setup with three undoable steps; chatbot disclosure with local detection of more than 40 vendors and the notice as first bot message, next to the widget or in the footer.
* Structured data: Article node for AI-written posts, stable ids, digitalSourceType as Schema.org enumeration and IPTC URI.

= 1.0.2 =
* Fixed: the library scan stopped after its first batch on some sites; large PNG files with metadata after the image data were reported as clean; images from Bing Image Creator, Microsoft Designer and Copilot were only queued instead of labeled.
* The file inspection says whether the attachment is labeled at all.

= 1.0.1 =
* Fixed: the hourly integrity sweep was not scheduled on sites created in a multisite network after activation.
* Per-file history, CSV audit export, file inspection with the raw XMP packet, optional delivery check for CDNs that strip metadata, translations for German, French, Spanish, Italian and Dutch.

= 1.0.0 =
* Initial release: C2PA, XMP/IPTC, PNG-chunk, EXIF, MP4 and MP3 detection with a camera rule and a review queue; visible badge with overlay guard, per-image override and CSS utility classes; IPTC digital source type written as XMP into JPEG, PNG, WebP and AVIF with auto-repair; Schema.org JSON-LD; page-cache purging; WP-CLI; integrations for AI Engine, AI Power, Elementor AI and WordPress AI; no external requests.

== Upgrade Notice ==

= 1.0.3 =
Adds disclosure levels for AI-written text, declarations for camera photos and human work, WooCommerce variation and lightbox badges, a REST API, a fuller audit trail with print view, a first-run setup and chatbot disclosure. Existing labels and settings carry over unchanged.

= 1.0.2 =
Fixes a library scan that stopped after its first batch, detection of large PNG files whose metadata sits after the image data, and the labeling of images from Bing Image Creator, Microsoft Designer and Copilot.

= 1.0.1 =
Fixes a silent failure of the auto-repair on multisite networks, adds a per-file history with CSV audit export, file inspection in the attachment details, an optional delivery check and five translations.

= 1.0.0 =
Initial release.
