{"slug": "how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned", "title": "How I Built an AI Alt Text Generator for WordPress — and What I Learned", "summary": "A developer built an AI alt text generator for WordPress to automate the creation of descriptive alt text for images, improving accessibility and SEO. The project uses a stack including a WordPress plugin, backend API, Stripe for billing, and PostHog for analytics. The developer learned key lessons about telemetry, including the importance of clear event semantics, deduplication, and privacy safeguards.", "body_md": "Accessibility is one of those areas everyone agrees matters, but it often gets pushed down the development queue. Alt text is a good example.\n\nAdding descriptive alt text to every image improves accessibility, helps screen-reader users understand a page, and can support SEO. But for sites with hundreds or thousands of images, writing it manually is repetitive and easy to neglect.\n\nThat problem led me to build an AI alt text generator for WordPress.\n\nWordPress makes it easy to upload images, but maintaining accurate alt text across a large media library is another story. Site owners usually face one of three situations:\n\nI wanted a tool that could cut that workload while keeping the site owner in control.\n\nThe goal isn't to remove human judgment — it's to make the first draft dramatically faster.\n\nThe project grew into more than a simple WordPress plugin. The current stack:\n\nThe WordPress plugin sends an authenticated generation request to the backend. The backend validates the user, checks available quota, processes the image, stores the usage result, and returns the generated description.\n\nFor billing, Stripe webhooks are the authoritative source for subscription status. The frontend never assumes a payment succeeded just because the user returned from checkout.\n\nOne of the most useful lessons came from telemetry. At one point the analytics showed:\n\nThat looked like duplicated completion events. The real issue was that the two metrics measured different things: a generation *start* could represent one bulk job, while *completion* events represented each image inside that job. Comparing them directly was like comparing shopping trips with items purchased.\n\nI replaced the ambiguous lifecycle with explicit events:\n\n`generation_job_started`\n\n`generation_item_completed`\n\n`generation_job_completed`\n\n`generation_job_failed`\n\nEach job now has a `generation_run_id`\n\n, and each image can have its own `generation_item_id`\n\n. That makes it possible to answer useful questions:\n\nClear event semantics turned out to be as important as collecting the events.\n\nAnalytics code can fire more often than expected. Events may be duplicated by:\n\nTo make events retry-safe, I added stable PostHog `$insert_id`\n\nvalues and defined which system owns each event:\n\nThis stops the same business action being counted two or three times by different parts of the app.\n\nA single checkout can pass through:\n\n`WordPress → Backend API → Render logs → Stripe Checkout → Stripe webhook → Supabase → PostHog`\n\nWithout a shared identifier, debugging that journey is painful. I introduced:\n\n`correlation_id`\n\n`checkout_attempt_id`\n\n`generation_run_id`\n\n`signup_attempt_id`\n\n`session_id`\n\n`site_install_id`\n\nThese let me trace one action from the plugin through the backend and into external services — especially useful when a checkout is abandoned or a login fails. Instead of searching disconnected systems by timestamp, the same correlation value appears throughout the journey.\n\nA generic `login_failed`\n\nevent isn't very useful. It doesn't tell you whether the cause was incorrect credentials, a disabled account, rate limiting, a network timeout, an unavailable API, token-creation failure, or session-storage failure.\n\nI added a controlled internal error taxonomy while keeping public error messages generic — that distinction matters because detailed public messages can reveal whether an account exists. The system now records safe internal codes such as:\n\n`invalid_credentials`\n\n`account_disabled`\n\n`rate_limited`\n\n`network_timeout`\n\n`api_unavailable`\n\n`token_creation_failed`\n\n`session_creation_failed`\n\n`unknown_auth_error`\n\nPasswords, tokens, API keys, and raw server responses are stripped before telemetry is sent.\n\nProduct analytics can become a privacy problem surprisingly quickly. The telemetry layer now removes fields such as:\n\nPostHog session recording is disabled unless explicitly enabled. The analytics should describe what happened without copying the content the user was working with.\n\nIf I started again, I'd define the analytics contract before building the dashboards, documenting each event with:\n\nRetrofitting clean telemetry is possible, but it's much more work than designing it properly up front. I'd also add correlation IDs from day one — they're cheap to implement and hugely valuable once an app spans multiple services.\n\nThe biggest lesson: building the AI generation feature was only one part of the product. A production-ready plugin also needs:\n\nThe AI part may be the headline feature, but reliability is what turns it into a usable product.\n\nI'm also continuing to improve how generated alt text is reviewed and applied within WordPress.\n\nI'd love to hear from other WordPress, accessibility, or SaaS developers: **what's been the hardest part of making your plugin production-ready?**", "url": "https://wpnews.pro/news/how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned", "canonical_source": "https://dev.to/benoats/how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned-4292", "published_at": "2026-07-16 22:05:54+00:00", "updated_at": "2026-07-16 22:35:18.871344+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools", "ai-tools"], "entities": ["WordPress", "Stripe", "PostHog", "Supabase"], "alternates": {"html": "https://wpnews.pro/news/how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned", "markdown": "https://wpnews.pro/news/how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned.md", "text": "https://wpnews.pro/news/how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned.txt", "jsonld": "https://wpnews.pro/news/how-i-built-an-ai-alt-text-generator-for-wordpress-and-what-i-learned.jsonld"}}