Joomla is a powerful content management system, and much of that power comes from its extensions ecosystem — the ability to add functionality without destabilising the core. Extensions are opaque, though, and there is a lot to get to grips with before you can build one successfully. You need to understand the directory structure, the MVC pattern, manifest files, and a handful of Joomla-specific conventions. You could use a component generator to handle the scaffolding, but I wanted to see how far AI could carry me. The answer, it turns out, is quite far — far enough that I shipped two working extensions in under a day, and far enough that those early experiments eventually became a fully productised, publicly available package. This article walks through how I built a Joomla plugin and component using AI assistance, explains where the AI got things wrong, and shows how that rough prototype became MetaGen — a free, open-source extension now available on the Joomla Extension Directory and compatible with Joomla 4.4, 5.x, and 6.x.
The problem I was solving: my article meta descriptions were poor. I'm not entirely convinced they carry the SEO weight they once did, but they still matter for click-through rates in search results, and I didn't want to spend time writing them manually for every article. The goal was to generate them automatically on save, and to have a bulk regeneration tool for when I changed the generation logic. We'll cover the plugin event hook, the MVC component structure, the controller and model, and the UI for a "Regenerate All" button. By the end, you'll understand how to build a functional Joomla extension that automatically fills the metadesc field — and you'll see how a working prototype like this can be taken all the way to a published, production-ready package. You can learn more about Joomla development at the Joomla developer website.
TL:DR – The following guide walks through building two Joomla extensions — a content plugin and an admin component — that automatically generate SEO-friendly meta descriptions. You'll see how to create the necessary MVC files, handle database updates, and add a button for bulk regeneration. The prototype code shown here directly informed MetaGen, a free package (pkg_metagen) now published at version 3.1.7 and available for Joomla 4.4 through 6.x.
Contents
- Getting your environment set up
- Generating the plugin
- AI prompt — Explain how to make a plugin
- Plugin structure
- Plugin event hook
- Generating the meta description
- AI prompt — fixing the generated example
- Plugin code (autometa.php)
- autometa.php
- Plugin manifest (autometa.xml)
- autometa.xml
- Installation and activation
- Testing the plugin
- Case 1 — Article with introtext
- Example outputs
- Generating the component
- AI prompt — running the task across all articles
- Setting up the component structure
- Folder structure
- Creating the model
- models/autometa.php
- Adding the controller logic
- controller.php
- Building the user interface
- views/autometa/tmpl/default.php
Getting your environment set up
To create a Joomla content plugin and a component that automatically generate meta descriptions from the title and content of an article, you'll need the following:
- Joomla installed (latest production version — Joomla 5.x is the current stable series as of 2026, with 6.x in early adoption)
- PHP 8.1 or later (required by the current Joomla ecosystem)
- MySQL 8.0 or MariaDB 10.4 or later
- Access to Joomla's filesystem and database
- A basic understanding of Joomla's extensions system
Generating the plugin
I used AI to help generate the source code for the plugin. The prompt was deliberately simple — I wanted to see how much the AI could infer from a plain-language description of the goal.
AI prompt — Explain how to make a plugin
Plugin structure
A Joomla content plugin resides in plugins/content/yourpluginname and typically includes:
yourpluginname.php(main plugin file)yourpluginname.xml(plugin descriptor/manifest)
Plugin event hook
You should use Joomla's onContentBeforeSave event to intercept and modify the article's metadata before it is saved to the database. This means the generation is invisible to the editor — it simply happens as part of the normal save process.
Generating the meta description
A meta description can safely run to 160 characters. Google has occasionally displayed longer snippets, but 160 remains the practical safe limit for search result display. The plugin needs to:
- Extract text from
$article->titleand$article->introtext - Strip HTML tags, remove excessive whitespace, and decode HTML entities
- Trim the result to 160 characters
- Assign the generated string to
$article->metadesc - Skip generation if a meta description has already been set manually
The AI generated a working skeleton, but it wasn't right out of the box. Its most significant mistake was attempting to store the metadata as a JSON-encoded attribute rather than a plain string. A single corrective prompt fixed it.
AI prompt — fixing the generated example
That single clarification was all it took. The AI revised its output, and after tidying the code and adding a licence, I had a working plugin. I added the GNU/GPLv3 licence (http://www.gnu.org/licenses/gpl-3.0.html) — Joomla's preferred licence for extensions — because the AI had not included one in its generated snippets.
Plugin code (autometa.php)
autometa.php
<?php
/*
* @package Plugin Autometa for Joomla!
* @version 1.1.0 autometa.php
* @author Angus Fox
* @copyright (C) 2025 - Multizone Limited
* @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
*/
defined('_JEXEC') or die;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Factory;
class PlgContentAutoMeta extends CMSPlugin
{
public function onContentBeforeSave($context, $article, $isNew)
{
// Ensure it's a Joomla article
if ($context !== 'com_content.article') {
return true;
}
// Skip if a meta description already exists
if (!empty($article->metadesc)) {
return true;
}
// Generate a meta description using the title and introtext
$article->metadesc = $this->generateMetaDescription($article->title, $article->introtext);
return true;
}
private function generateMetaDescription($title, $introtext)
{
$summary = $this->extractText($introtext);
$metaDesc = trim($title);
if (!empty($summary)) {
$metaDesc .= ' - ' . $summary;
}
return mb_substr($metaDesc, 0, 160);
}
private function extractText($text)
{
// Remove HTML tags, decode special characters, and clean up spaces
$cleanText = trim(strip_tags(html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8')));
return $cleanText;
}
}
Plugin manifest (autometa.xml)
This defines the plugin metadata and installation parameters. Note the version="5.0" attribute in the extension element, which signals compatibility with the Joomla 5.x series.
autometa.xml
<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" version="5.0" group="content" method="upgrade">
<name>PLG_CONTENT_AUTOMETA</name>
<version>1.1.0</version>
<creationDate>19 February 2025</creationDate>
<author>Angus Fox</author>
<copyright>(C) 2025 Multizone Limited. All rights reserved.</copyright>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it. </authorEmail>
<authorUrl>https://www.multizone.co.uk</authorUrl>
<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
<description>PLG_CONTENT_AUTOMETA_XML_DESCRIPTION</description>
<files>
<filename plugin="autometa">autometa.php</filename>
<folder>language</folder>
</files>
</extension>
Installation and activation
- Zip
autometa.phpandautometa.xmlinto a package - Add the GPL licence text file
- Install via Joomla's Extensions Manager
- Enable the plugin in Joomla's Plugin Manager
Every new article will now receive a generated meta description if one hasn't been set manually.
Testing the plugin
There are three cases worth testing explicitly:
- Case 1: Article with introtext — the title and stripped introtext are combined
- Case 2: Article without introtext — only the title is used
- Case 3: No text at all — the field is left empty rather than populated with a broken string
Case 1 — Article with introtext
<p class="lead">AI is changing the world.</p>
<p>New developments in machine learning...</p>
Generated meta description
Article Title - AI is changing the world.
Example outputs
| Title | Introtext | Generated meta description |
|---|---|---|
| "Exciting Tech News" | "AI is transforming the industry..." | "Exciting Tech News - AI is transforming the industry..." |
| "Future of Space" | "<p>NASA plans new Mars missions...</p>" | "Future of Space - NASA plans new Mars missions..." |
Generating the component
The plugin handles individual articles on save, but there are times when you need to regenerate meta descriptions across your entire article library — when you change the generation logic, for instance, or when you've imported a batch of articles without descriptions. For that, you need an administrator component with a "Regenerate All" button.
AI prompt — running the task across all articles
Setting up the component structure
Joomla components require a structured directory layout. This isn't the most elaborate MVC structure Joomla supports, but it is clean and sufficient. The meta description logic lives in the model, making it reusable. The controller handles the user action. The view renders the UI. Concerns are separated, and the code is easy to maintain.
Folder structure
/com_autometa/
│── autometa.php # Main entry file
│── controller.php # Handles actions
│── manifest.xml # XML file detailing component information
│── models/
│ ├── autometa.php # Processes meta descriptions
│── views/
│ ├── autometa/
│ │ ├── view.html.php
│ │ ├── tmpl/
│ │ │ ├── default.php # UI for regenerating metadata
Creating the model
The model fetches all articles, generates a meta description for each, and updates the database. This is a destructive operation — it will overwrite existing meta descriptions. Take a backup before running it.
models/autometa.php
<?php
defined('_JEXEC') or die;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Factory;
class AutometaModelAutometa extends BaseDatabaseModel
{
public function regenerateAllMetaDescriptions()
{
$db = Factory::getDbo();
// Select all articles
$query = $db->getQuery(true)
->select(['id', 'title', 'introtext'])
->from('#__content');
$db->setQuery($query);
$articles = $db->loadObjectList();
// Loop through each article and update meta description
foreach ($articles as $article) {
$metaDesc = $this->generateMetaDescription($article->title, $article->introtext);
$updateQuery = $db->getQuery(true)
->update('#__content')
->set($db->quoteName('metadesc') . ' = ' . $db->quote($metaDesc))
->where($db->quoteName('id') . ' = ' . (int) $article->id);
$db->setQuery($updateQuery);
$db->execute();
}
}
private function generateMetaDescription($title, $introtext)
{
$cleanIntro = strip_tags($introtext);
$cleanIntro = trim($cleanIntro);
$summary = mb_substr($cleanIntro, 0, 150);
return $title . ' - ' . $summary;
}
}
Adding the controller logic
The controller handles the button click, calls the model, and redirects back to the component with a status message.
controller.php
<?php
defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Factory;
class AutometaController extends BaseController
{
public function regenerateAll()
{
$model = $this->getModel('Autometa', 'AutometaModel', ['ignore_request' => true]);
if ($model) {
$model->regenerateAllMetaDescriptions();
Factory::getApplication()->enqueueMessage('All meta descriptions regenerated.', 'message');
} else {
Factory::getApplication()->enqueueMessage('Error: Could not load model.', 'error');
}
$this->setRedirect('index.php?option=com_autometa');
}
}
Building the user interface
The UI is deliberately minimal — a single button that submits a POST request to trigger the controller action. In the production MetaGen package this has been expanded into a proper admin dashboard, but for a working prototype this is all you need.
views/autometa/tmpl/default.php
<?php
defined('_JEXEC') or die;
use Joomla\CMS\Router\Route;
?
