=== AmazImg Image Description Generator ===
Contributors: m1sh0u
Tags: alt text, accessibility, image seo, ai, media library
Requires at least: 7.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Generate accessible, SEO-friendly image alt text with the WordPress AI Client and the AI provider you connected.

== Description ==

Missing alt text hurts accessibility (WCAG / European Accessibility Act) and image SEO. Amazimg writes concise, descriptive alt text for your images using a vision AI model of your choice.

**See it in action (~4 minutes):**

https://www.youtube.com/watch?v=acEMRWrw7CI

**Features**

* One-click "Generate alt text" button in the media modal, attachment edit screen and Media Library list view.
* "Alt text" column in the Media Library list view that shows which images are missing alt text.
* Overview page with alt text coverage stats and a list of images that still need alt text.
* Built on the WordPress AI Client: works with the provider you connected in Settings → Connectors (OpenAI, Anthropic Claude, Google Gemini or any other provider plugin with vision models). No extra API keys, no middleman, no credits to buy.
* Uses context (file name, image title, the page the image was uploaded to) for more relevant results.
* Writes in your site language or any language you choose.
* Lightweight: no external scripts and no tracking. Nothing runs on the front end.

**Pro add-on**

Unleash the power of AI with the [AmazImg Pro add-on](https://amazimg.pro/#pricing).

We offer a comprehensive range of advanced features designed to streamline your processes and boost efficiency. From intuitive user interface to seamless integration, our software provides everything you need to optimize your workflow and achieve exceptional results.

Pro features include:

* bulk generation for your whole library
* automatic alt text on upload
* a review queue with undo
* alt text sync into existing posts
* spending caps
* WPML/Polylang support
* WooCommerce and SEO plugin context
* a block editor panel
* WP-CLI and REST API
* custom prompts, titles, captions and long descriptions
* scheduled background runs.

**Note:** The first 100 customers get a **50% discount**. Use the promo code: **FIRST100** to apply the discount to your subscription.

[Order AmazImg Pro add-on now](https://amazimg.pro/#pricing)

== External services ==

This plugin does not contact any AI service itself. It uses the WordPress AI Client (built into WordPress 7.0+), which sends requests to the AI provider the site owner connected in `Settings → Connectors`. Nothing is sent until a provider is connected and you generate alt text, either by clicking a "Generate" button or through a Pro automation you turn on.

For each generation the image (a resized copy when available), a text prompt and short context (file name, image title, title of the page the image is attached to) are sent to the connected provider, for example:

* **OpenAI** (api.openai.com): [Terms of use](https://openai.com/policies/terms-of-use), [Privacy policy](https://openai.com/policies/privacy-policy)
* **Anthropic** (api.anthropic.com): [Commercial terms](https://www.anthropic.com/legal/commercial-terms), [Privacy policy](https://www.anthropic.com/legal/privacy)
* **Google Gemini** (generativelanguage.googleapis.com): [Gemini API terms](https://ai.google.dev/gemini-api/terms), [Privacy policy](https://policies.google.com/privacy)

**AmazImg news (optional, off by default).** If an administrator turns on "News and tips" in Media → AI Alt Text → Settings, the plugin downloads a short list of messages from `https://amazimg.pro/wp-json/amazimg/v1/notices` at most about twice a day, when that screen is opened. The request sends only the plugin version; like any web request, it also reveals the site's IP address to the server. Nothing is requested while the option is off. [Terms of service](https://amazimg.pro/terms/), [Privacy policy](https://amazimg.pro/privacy-policy/)

== Installation ==

1. You can install the plugin by **uploading** the **.zip** file in the **plugins section** of Wordpress, or by adding the files to the folder `/wp-content/plugins/amazimg-image-description-generator`.
2. Go to **Settings → Connectors**, install a provider plugin (OpenAI, Anthropic or Google) and add its API key.
3. Optional: in **Media → AI Alt Text → Settings**, list the models you prefer, the output language and the maximum length.
4. Open any image in the Media Library and click **Generate alt text**.

== Frequently Asked Questions ==

= Where do I enter my API key? =

In **Settings → Connectors** (WordPress 7.0+). The plugin never stores API keys; it uses the WordPress AI Client, so every AI feature on your site shares the same connection. Keys can also come from the `OPENAI_API_KEY`, `ANTHROPIC_API_KEY` or `GOOGLE_API_KEY` constants or environment variables.

= Which model is used? =

WordPress picks a connected model that can read images. To choose, enter one or more model ids under **Media → AI Alt Text → Settings → Preferred models**.

= How much does it cost? =

The plugin is free. You pay your AI provider directly. With the default small models, a single image typically costs a fraction of a cent.

= Does it overwrite my existing alt text? =

Only when you click "Regenerate" on an image that already has alt text.

= Which image formats are supported? =

JPEG, PNG, GIF and WebP.

= My images are on a CDN / S3. Does it work? =

Yes. If the file is not on the server, the plugin downloads the "large" size from its public URL.

== Screenshots ==

1. Plugin overview
2. Activity & Reports
3. Settings for the free version
4. Automation & Usage limits settings
5. Content settings
6. Alt text in posts & Exclusions settings
7. Generate alt text button in the media modal

== Developers ==

AmazImg Image Description Generator can be extended with PHP hooks and a small JavaScript API. The Pro add-on also adds a REST API and WP-CLI commands.

= Filters =

* `aatg_generate_args` ( $args, $attachment_id ): change the generation arguments.
* `aatg_pre_generate` ( null, $attachment_id, $args ): return a `WP_Error` to stop generation for an image.
* `aatg_context` ( $context, $attachment_id ): add context to the prompt, such as a post title or product name.
* `aatg_language` ( $language, $attachment_id ): choose the output language per image.
* `aatg_prompt` ( $prompt, $attachment_id, $context ): change the prompt sent to the AI.
* `aatg_ai_prompt_builder` ( $builder, $image, $prompt ): adjust the WordPress AI Client request before it is sent.
* `aatg_max_tokens` ( $max_tokens ): change the output limit (default 1024).
* `aatg_image_sizes` ( $sizes ): choose which image size is sent to the AI.
* `aatg_parse_response` ( null, $raw, $attachment_id ): parse a structured reply. Return an array with an `alt` key.
* `aatg_is_decorative` ( false, $attachment_id ): mark an image as decorative (empty alt text).
* `aatg_query_args` ( $query_args, $purpose, $args ): change which images are found.

= Actions =

* `aatg_before_save` ( $attachment_id, $result, $args ): runs just before alt text is saved.
* `aatg_generated` ( $attachment_id, $result, $context, $args ): runs after a successful generation.
* `aatg_generate_failed` ( $attachment_id, $error, $args ): runs after a failed generation.
* `aatg_usage` ( $provider, $model, $input_tokens, $output_tokens ): reports the AI usage of each request.

= Error codes =

* `aatg_http_429`: the AI provider is rate-limiting requests. Retry later.
* `aatg_http_5xx` (for example `aatg_http_503`): the AI provider is temporarily unavailable. Retry later.
* `aatg_http_error`: network error reaching the AI provider. Retry later.
* `aatg_ai_error`: any other AI request failure, for example an invalid API key. Don't retry.
* `aatg_no_key`: no AI provider is connected in Settings → Connectors.
* `aatg_unsupported`: the file type is not supported. Use JPEG, PNG, GIF or WebP.

= Examples =

Add brand guidance to every prompt:

`
add_filter( 'aatg_prompt', function ( $prompt, $attachment_id, $context ) {
	return $prompt . "\nMention the brand name if a logo is visible.";
}, 10, 3 );
`

Skip images uploaded to a "logos" folder:

`
add_filter( 'aatg_pre_generate', function ( $error, $attachment_id ) {
	if ( false !== strpos( (string) get_attached_file( $attachment_id ), '/logos/' ) ) {
		return new WP_Error( 'my_skip', 'Logos are handled manually.' );
	}
	return $error;
}, 10, 2 );
`

Log every generated alt text:

`
add_action( 'aatg_generated', function ( $attachment_id, $result ) {
	error_log( sprintf( 'Alt text for #%d: %s', $attachment_id, $result['alt'] ) );
}, 10, 2 );
`

= JavaScript =

In the admin, `AATG.generate( attachmentId, options )` returns a jQuery promise, and the `aatg:generated` event fires after each success:

`
AATG.generate( attachmentId, { source: 'my-plugin' } )
	.done( function ( data ) { console.log( data.alt ); } );

jQuery( document ).on( 'aatg:generated', function ( event, attachmentId, data ) {
	// data.pending is set when the result was held for review.
} );
`

= REST API (Pro) =

The Pro add-on adds routes under `/wp-json/amazimg-pro/v1`. To call them from outside WordPress, sign in with an application password (Users → Profile → Application Passwords) using HTTP Basic auth.

* `GET /stats`: total images, images missing alt text, items pending review, queue size, and this month's usage and estimated cost. Needs the `upload_files` capability.
* `GET /images?status=missing|low|all&page=1&per_page=20`: lists images with their alt text, SEO score and issues, any pending suggestion, and whether undo is possible. Paging headers: `X-WP-Total` and `X-WP-TotalPages`. Needs `upload_files`.
* `POST /images/{id}/generate`: generates alt text for one image. Parameters: `overwrite` (default false), `save` (default true; false returns only a suggestion) and `skip_review` (default false). Needs permission to edit the image.
* `POST /images/{id}/undo`: restores the alt text from before the last AI change. Returns 409 when there is nothing to undo. Needs permission to edit the image.
* `GET /queue`: queue size and the last error. Needs `upload_files`.
* `POST /queue`: adds images to the background queue. Pass `ids` (an array of attachment IDs) or `scope` (`missing`, `low` or `all`), plus `overwrite`. Needs `upload_files`.

When the monthly spending cap is reached, `generate` returns HTTP 429 with the code `aatgp_budget`.

`
curl -u 'admin:xxxx xxxx xxxx xxxx' -X POST \
  'https://example.com/wp-json/amazimg-pro/v1/images/123/generate?save=false'
`

= WP-CLI (Pro) =

`
wp amazimg generate --limit=500
wp amazimg generate 12 34 --overwrite
wp amazimg generate --scope=low --products --skip-review
wp amazimg generate --queue
wp amazimg generate --dry-run
wp amazimg undo 12 34
wp amazimg undo --run=<run-id>
wp amazimg review list|approve|reject [<id>...]
wp amazimg sync-content [--replace] [--dry-run]
wp amazimg stats --format=json
wp amazimg queue status|run|clear
`

Rate limits and provider outages are retried automatically, up to 3 times, 30 seconds apart. Run `wp help amazimg` for the full reference.

== Changelog ==

= 1.0.0 =

* Initial release.
