avh/contao-faq-structured-bundle

SEO/AEO-optimized FAQ content element with Schema.org FAQPage JSON-LD and three template variants (Handorgel, Bootstrap 5, Tailwind CSS)

Maintainers

Package info

github.com/avhulst/AvhContaoFaqStructuredBundle

Type:contao-bundle

pkg:composer/avh/contao-faq-structured-bundle

Statistics

Installs: 21

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

1.0.0 2026-03-08 13:00 UTC

This package is auto-updated.

Last update: 2026-03-09 10:21:08 UTC


README

Package name: avh/contao-faq-structured-bundle

Short description: Custom Contao content element for SEO/AEO-optimized FAQ sections with automatic Schema.org FAQPage JSON-LD output and three template variants (Handorgel, Bootstrap 5, Tailwind CSS).

Target Audiences

  • Developers: Technical integration of the bundle into Contao 5.7, template customization, extending FAQ logic.
  • Project Managers: Understanding SEO benefits (Rich Results in Google), feature overview for client consulting and project planning.

Core Features

  1. FAQ Content Element — New content type faq_structured in the Texts category. Unlimited question-answer pairs per element.
  2. Schema.org FAQPage JSON-LD — Automatic generation of structured data in FAQPage format. Output in the <head> of the page.
  3. Three Template Variants — Handorgel (default), Bootstrap 5 Accordion, Tailwind CSS with <details> element.
  4. Rich-Text Answers — Answers are edited via TinyMCE and support HTML formatting (links, lists, bold text, etc.).

Technical Architecture

Directory Structure

custom/bundles/ContaoFaqStructuredBundle/
├── .editorconfig                                  # Code style configuration
├── .gitignore                                     # Git ignore rules
├── .gitlab-ci.yml                                 # CI/CD pipeline
├── CHANGELOG.md                                   # Changelog
├── LICENSE                                        # MIT license
├── README.md                                      # Documentation (English)
├── README_DE.md                                   # Documentation (German)
├── cliff.toml                                     # git-cliff changelog configuration
├── composer.json                                  # Package definition, dependencies
├── config/
│   └── services.php                               # Service autowiring
├── contao/
│   ├── dca/
│   │   └── tl_content.php                         # Backend field definitions (palette, fields)
│   ├── languages/
│   │   ├── de/default.php                         # German labels
│   │   └── en/default.php                         # English labels
│   └── templates/twig/
│       ├── .twig-root                             # Namespace root marker
│       └── content_element/
│           ├── faq_structured.html.twig           # Default template (Handorgel)
│           └── faq_structured/
│               ├── bootstrap.html.twig            # Bootstrap 5 Accordion
│               └── tailwind.html.twig             # Tailwind CSS Details
└── src/
    ├── ContaoFaqStructuredBundle.php               # AbstractBundle (loads services.php)
    ├── ContaoManager/
    │   └── Plugin.php                              # Bundle registration via BundlePluginInterface
    └── Controller/
        └── ContentElement/
            └── FaqStructuredController.php         # Content element logic

Request Flow

  1. Contao renders the content element faq_structured
  2. FaqStructuredController::getResponse() is called
  3. FAQ entries are deserialized from the serialized faqItems field and filtered
  4. Schema.org FAQPage JSON-LD is built as an array
  5. Template receives: faq_items, schema_org_data, accordion_id
  6. JSON-LD is injected into the <head> via {% do add_schema_org(schema_org_data) %}

Dependencies

Package Version Purpose
php ^8.3 Minimum PHP version
contao/core-bundle ^5.7 Contao framework
mvo/contao-group-widget ^1.6 Repeatable field groups in the backend (inputType group)

Setup / Installation

Requirements:

  • Contao Managed Edition 5.7
  • PHP 8.3+
  • mvo/contao-group-widget ^1.6 (automatically installed as a dependency)

Installation:

The bundle is located as a local package under custom/bundles/ContaoFaqStructuredBundle/. It is included via the repositories configuration in the project's composer.json.

ddev composer install

After changes to Plugin.php, ddev composer install must be run again — a cache:clear is not sufficient.

Configuration & Usage

Backend Operation

  1. Create content element: In the article section, create a new content element of type FAQ (Structured Data) (category: Texts).
  2. Manage questions and answers: In the FAQ Entries section, add any number of question-answer pairs. Answers support rich text (TinyMCE).
  3. Select template: Use the Custom Template field (customTpl) to choose one of the three variants. Without selection, the Handorgel template is used.

Available Backend Fields

Field Type Description
faqItems Group widget Repeatable question-answer pairs
faqQuestion Text Question text (max. 512 characters, required)
faqAnswer Textarea (RTE) Answer text with TinyMCE editor (required)

Template Variants

Variant File CSS/JS Dependency Behavior
Handorgel (default) faq_structured.html.twig contao-components/handorgel (CSS + JS, automatically included) First item open, only one item at a time (multiSelectable: false)
Bootstrap 5 faq_structured/bootstrap.html.twig Bootstrap 5 must be available in the project Accordion with data-bs-toggle="collapse", first item open
Tailwind CSS faq_structured/tailwind.html.twig Tailwind CSS must be available in the project Native <details>/<summary> element, no JavaScript, first item open

Template Selection Guide

  • Handorgel: Standalone solution without framework dependency. Suitable for projects without a CSS framework.
  • Bootstrap 5: When the project already uses Bootstrap 5. Seamless integration with existing accordion styling.
  • Tailwind CSS: Minimal footprint, no JavaScript. Uses native browser behavior (<details>). Ideal for Tailwind projects.

Schema.org / SEO

The bundle automatically generates FAQPage JSON-LD for each FAQ element. The structure is inserted into the <head> via Contao's add_schema_org() function in the template's metadata block.

Example Output

{
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
        {
            "@type": "Question",
            "name": "What is Contao?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Contao is an open-source content management system."
            }
        }
    ]
}

Allowed HTML Tags in Answers (JSON-LD)

In the JSON-LD output, answers are sanitized with strip_tags(). The following tags are preserved:

<a>, <b>, <strong>, <i>, <em>, <br>, <p>, <ul>, <ol>, <li>

Google Rich Results

  • FAQPage markup enables FAQ Rich Results in Google Search (expandable questions directly in the search result).
  • Validation via the Google Rich Results Test Tool.

Important Notes

  • Dependency mvo/contao-group-widget: The bundle uses the inputType group for repeatable field groups. Without this package, the backend form will not work.
  • Cache: After changes to FAQ content, the page cache must be refreshed for the updated JSON-LD data to be served.
  • Empty entries: Question-answer pairs without a question or answer are automatically filtered out and appear neither in the frontend nor in the JSON-LD.
  • .twig-root file: The file contao/templates/twig/.twig-root is mandatory for Contao to correctly recognize the template variants.
  • Extensibility: Custom template variants can be added as subfolder templates under contao/templates/twig/content_element/faq_structured/. Alternatively, templates can be overridden in the project under templates/.