=== Alt Text BYOK ===
Contributors: deusacc
Tags: alt text, accessibility, ai, media library, seo
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.3.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Automatically generate ALT text for your Media Library images with a vision AI model — bring your own API key (BYOK), no plugin subscription.

== Description ==

Images without ALT text are both an accessibility problem (screen readers) and an SEO problem. This plugin scans your Media Library, finds images with no ALT text and generates a description automatically, calling any vision-capable AI endpoint compatible with the OpenAI API (OpenAI itself, or any compatible provider — including providers with free tiers). One-click presets fill in the endpoint and a vision model for OpenAI, Anthropic (Claude), Google Gemini, Groq, OpenRouter, Mistral and Ollama (local, no API cost).

Features:

* A dedicated Media > Alt Text BYOK page listing every image without ALT text.
* Generate one image at a time, or all of them in sequence with one click.
* No cost for the plugin itself: you use your own API key and only pay (if at all) the provider you choose.
* Configurable ALT text language, or automatic: on multilingual sites it follows the WPML or Polylang language of the page the image belongs to.
* Option to regenerate images that already have ALT text.

BYOK (Bring Your Own Key): the plugin ships no API key of its own and does not act as a paid intermediary — a specific requirement of the WordPress.org policy on plugins that use external services, and at the same time the reason it costs less than subscription-based competitors.

= Free vs Full version =

This version is complete and has no usage limits: generate ALT text for as many images as you like, forever. [The full version](https://shop.lumnika.com/alt-text-byok.html) is a one-time payment (no subscription; the license key inside your download keeps it updated automatically) for sites that want more automation:

* ALT text generated automatically for every new image as soon as it is uploaded.
* Images sent inline (base64) instead of by URL, so it works on local, staging and password-protected sites the AI provider cannot reach.
* A WP-CLI command, `wp alt-text generate`, to process large libraries from the command line.
* WooCommerce: product images get the product name as context, for more precise ALT text.
* Page and SEO context: the title of the page the image is attached to, its Yoast SEO or Rank Math focus keyword and a meaningful file name go into the prompt.
* Background backlog: every existing image without ALT text is processed in hourly batches by WP-Cron, no browser tab to keep open; rate limits pause the queue and it resumes on its own.
* Optional title and caption: the generated text also fills an empty caption, and the title when it is still the file name.
* ALT text in existing posts: WordPress copies the ALT into a post only when the image is inserted, so pages published earlier keep an empty alt. The full version shows the Media Library ALT in those pages, and `wp alt-text sync-content` writes it into the posts (a revision keeps the previous version).

== External services ==

This plugin sends image data to the AI endpoint that you configure yourself in the settings (API base URL, API key and model). No request is sent anywhere until you enter your own credentials, and no data passes through any server belonging to the plugin author. Which provider receives the data, and under which terms and privacy policy, is entirely your choice — by default the plugin points at the OpenAI chat completions API (https://openai.com/policies/terms-of-use, https://openai.com/policies/privacy-policy). On WordPress 7.0+ you can instead pick "WordPress AI": the image then goes through the AI client built into WordPress to the provider you connected in Settings > Connectors, under that provider's terms.

The full version (sold separately, not part of this build) also contacts shop.lumnika.com with its license key, at most once a week and only from the admin or WP-Cron, to check that the license is still valid and to offer updates (https://shop.lumnika.com). No site content or images are sent.

Optional setup tips: only if you tick "Send me setup tips" in the settings, the email address you enter is sent once to shop.lumnika.com (the plugin author's shop, https://shop.lumnika.com/) together with the plugin name, to send you a few setup tips by email. The box is unticked by default and nothing is sent otherwise.

== Installation ==

1. Upload the `alt-text-byok` folder to `/wp-content/plugins/`.
2. Activate the plugin from the WordPress Plugins menu.
3. Go to Settings > Alt Text BYOK and enter your API key (and, if you are not using OpenAI, your provider's URL and the model name).
4. Go to Media > Alt Text BYOK to generate the missing ALT texts.

== Frequently Asked Questions ==

= Can I use the AI already configured in WordPress, without a key? =
Yes, on WordPress 7.0 or newer. Connect a provider once in Settings > Connectors, then pick "WordPress AI" in this plugin's Provider list and save: no key is pasted here. Leave the model on "auto" to let WordPress choose, or type a model name you prefer. The connected provider must have a model that can read images; if none can, the plugin tells you instead of guessing. On older WordPress versions this option is simply not shown.

= Do I need an OpenAI key specifically? =
No. Any endpoint compatible with the OpenAI "chat completions" API that supports images will work: just change "API base URL" and "Model" in the settings.

= Does the plugin send my images to a server of its own? =
No. Requests go directly from your site to the API provider you configured yourself.

= What happens to images that already have ALT text? =
They are skipped by default. You can include them by ticking "Overwrite existing ALT" in the settings.

= Is there a limit on the number of images? =
No. The only cost is what your AI provider charges you, if anything (several providers have free tiers).

= Which providers have a free tier with image (vision) support? =
At the time of writing: Google Gemini (free tier from Google AI Studio, OpenAI-compatible URL `https://generativelanguage.googleapis.com/v1beta/openai/`), Groq (free tier with Llama vision models, `https://api.groq.com/openai/v1/`), OpenRouter (models marked ":free", `https://openrouter.ai/api/v1/`) and Mistral (free experiment plan, `https://api.mistral.ai/v1/`). Ollama runs a vision model such as Gemma 3 or Qwen2.5-VL on your own machine at no cost (`http://localhost:11434/v1/`). Free tiers have rate limits: the plugin waits and retries on its own. Providers change their free offers, so check their pricing page.

= What is removed when I delete the plugin? =
Its settings, queue state and scheduled events. The ALT texts already written to your images stay, because they are your content.

= My site is local or password-protected and the provider can't load the images. =
By default the plugin sends the image URL. The full version can send the image data itself, which works wherever your site can reach the provider.

== Screenshots ==

1. Media > Alt Text BYOK lists every image in your Media Library that has no ALT text.
2. One click generates ALT text for all of them with your own AI provider (here Groq, a free tier); rate limits are waited out automatically.
3. Settings: pick a provider preset (OpenAI, Anthropic, Gemini, Groq, OpenRouter, Mistral, Ollama or any OpenAI-compatible endpoint), paste your own API key; ALT language follows your site (WPML/Polylang aware).

== Changelog ==

= 1.3.0 =
* Out of API credit (OpenAI "insufficient_quota", Gemini daily quota) now stops the run with a clear "top up your credit" message instead of waiting and retrying.
* "Also generate for images that already have ALT text" now applies to the bulk page too: with it on, Generate for all covers every image.
* Bulk skips formats vision models reject (SVG, TIFF, BMP, AVIF) instead of failing on each one.
* Test connection no longer saves anything as a side effect, and respects unticked checkboxes.
* Users can only generate ALT text for images they are allowed to edit.

= 1.2.9 =
* ALT text in Japanese, Hindi, Thai, Russian and other non-Latin languages is no longer cut off mid-word: higher output limit, and a truncated reply is never saved (one shorter retry, then a clear error).
* Reasoning models (OpenAI o-series, GPT-5, Gemini 2.5/3 thinking) no longer return empty ALT text; OpenAI reasoning models get max_completion_tokens.
* Gemini errors now show the provider's real reason (e.g. "model no longer available") instead of only "HTTP 404".

= 1.2.8 =
* Bulk run stops at the first "API key rejected" (HTTP 401/403) instead of failing every image, with a link to Settings.

= 1.2.7 =
* Upgrade buttons in wp-admin go straight to checkout; "See what it adds" still opens the feature page.

= 1.2.6 =
* "Deactivate license on this site" button under the license key: frees this site's seat so the license can move to another domain without contacting support.

= 1.2.5 =
* A license key now counts the site it unlocks the full version on (3 sites per license); past the limit the full-version features turn off on that site with a clear notice and upgrade links.

= 1.2.4 =
* New: on WordPress 7.0+ you can pick "WordPress AI" as the provider: ALT text is generated through the AI client built into WordPress, using the connectors already set up in Settings > Connectors, so no API key is pasted into this plugin.

= 1.2.3 =
* Security hardening: the Media Library bulk action link now carries a nonce, and the connection test sanitizes every posted setting.

= 1.2.2 =
* After 25 and 100 ALT texts written one by one, a dismissible notice points to the full version (whole library, at upload).
* Settings: optional, unticked "Send me setup tips" email opt-in; the email is sent to shop.lumnika.com only if you tick it.

= 1.2.1 =
* Settings page: links to the other BYOK plugins from Lumnika (static links, no remote calls).

= 1.2.0 =
* Removed the monthly limit: this version is now unlimited.
* Internal: a single generation path shared by the bulk page and extensions.

= 1.1.1 =
* Bulk generation now waits and retries when the AI provider answers with a rate limit (common on free tiers) instead of failing the remaining images.
* Remaining admin messages translated to English.

= 1.1.0 =
* Added the free/full-version tier: 30 generations/month on the free version, unlimited in the full version (one-time purchase, no subscription).
* Fixed plugin header (Plugin URI, Author) and readme Contributors placeholder ahead of the WordPress.org submission.

= 1.0.0 =
* First release: BYOK ALT generation, bulk page, settings.
