ai-search-optimization by dirnbauer/webconsulting-skills
npx skills add https://github.com/dirnbauer/webconsulting-skills --skill ai-search-optimization范围: 针对 AI 驱动的搜索引擎和答案引擎优化内容。此技能涵盖在 ChatGPT、Perplexity、Google AI Overviews、Microsoft Copilot 和其他生成式 AI 平台中提高可见性的策略。
答案引擎优化侧重于构建内容,以通过 AI 驱动的平台为用户查询提供直接、简洁的答案。与旨在获取点击的传统 SEO 不同,AEO 优化的是内容被引用为答案来源。
目标平台:
生成引擎优化是更广泛的学科,旨在提升内容在AI 生成的搜索结果中的可见性。它针对那些从多个来源综合答案而非呈现传统链接列表的生成引擎。
与传统 SEO 的主要区别:
| 方面 | 传统 SEO | AEO/GEO |
|---|---|---|
| 目标 | 在 SERP 中排名 | 在 AI 答案中被引用 |
| 用户行为 | 点击进入网站 | 直接获取答案 |
| 内容格式 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 关键词优化页面 |
| 结构化、可引用的内容 |
| 成功指标 | 点击率 | 引用频率 |
| 查询类型 | 短关键词 | 对话式、长尾查询 |
AI 系统能更有效地从结构良好的内容中提取信息:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Descriptive, Question-Answering Title</title>
</head>
<body>
<article>
<header>
<h1>Primary Topic as Question or Clear Statement</h1>
<p class="summary">Direct 2-3 sentence answer to the main question.</p>
</header>
<main>
<section>
<h2>Subtopic Heading</h2>
<p>Detailed explanation with facts and data.</p>
<ul>
<li>Key point 1 with specific information</li>
<li>Key point 2 with verifiable data</li>
<li>Key point 3 with actionable insight</li>
</ul>
</section>
</main>
<aside>
<h3>Quick Facts</h3>
<dl>
<dt>Term</dt>
<dd>Definition</dd>
</dl>
</aside>
</article>
</body>
</html>
# H1: 主主题(包含主要问题/关键词)
└── ## H2: 主要子主题
└── ### H3: 具体方面
└── #### H4: 细节(谨慎使用)
规则:
为 AI 提取构建内容结构:
┌─────────────────────────────────────┐
│ 直接答案(前 1-2 句 │ ← AI 提取此部分
│ 直接回答查询) │
├─────────────────────────────────────┤
│ 关键事实与背景 │ ← 支持性证据
│ (要点、数据、引用) │
├─────────────────────────────────────┤
│ 详细解释 │ ← 全面覆盖
│ (背景、方法、 │
│ 示例、案例研究) │
├─────────────────────────────────────┤
│ 相关主题 │ ← 主题权威性信号
│ (指向相关内容的链接) │
└─────────────────────────────────────┘
AI 引擎偏好结构化数据格式:
<!-- 对比表格 -->
<table>
<caption>Feature Comparison: Product A vs Product B</caption>
<thead>
<tr>
<th>Feature</th>
<th>Product A</th>
<th>Product B</th>
</tr>
</thead>
<tbody>
<tr>
<td>Price</td>
<td>$99/month</td>
<td>$149/month</td>
</tr>
<!-- More rows -->
</tbody>
</table>
<!-- 术语定义列表 -->
<dl>
<dt>AEO</dt>
<dd>Answer Engine Optimization - optimizing content for direct answers</dd>
<dt>GEO</dt>
<dd>Generative Engine Optimization - visibility in AI-generated results</dd>
</dl>
<!-- 分步流程 -->
<ol>
<li>Step one with clear action</li>
<li>Step two with measurable outcome</li>
<li>Step three with verification method</li>
</ol>
研究表明,结构化数据能显著提高 AI 搜索可见性:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is Answer Engine Optimization?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Answer Engine Optimization (AEO) is a strategic approach to structuring content so AI platforms like ChatGPT, Perplexity, and Google AI Overviews can easily extract and cite it as direct answers to user queries."
}
},
{
"@type": "Question",
"name": "How is AEO different from SEO?",
"acceptedAnswer": {
"@type": "Answer",
"text": "While SEO focuses on ranking in traditional search results for clicks, AEO optimizes content to be cited directly in AI-generated answers, often resulting in zero-click interactions where users get information without visiting the source."
}
}
]
}
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to Optimize Content for AI Search",
"description": "Step-by-step guide to improving visibility in AI-powered search engines",
"totalTime": "PT30M",
"step": [
{
"@type": "HowToStep",
"name": "Structure Content Semantically",
"text": "Use proper HTML5 semantic elements like article, section, and aside",
"position": 1
},
{
"@type": "HowToStep",
"name": "Implement Schema Markup",
"text": "Add FAQPage, HowTo, and Article schema to your pages",
"position": 2
},
{
"@type": "HowToStep",
"name": "Optimize for Conversational Queries",
"text": "Write content that answers natural language questions",
"position": 3
}
]
}
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Complete Guide to AI Search Optimization",
"description": "Learn how to optimize content for ChatGPT, Perplexity, and Google AI Overviews",
"datePublished": "2025-01-15",
"dateModified": "2025-01-15",
"author": {
"@type": "Person",
"name": "Expert Name",
"url": "https://example.com/about/expert-name",
"jobTitle": "SEO Specialist",
"sameAs": [
"https://linkedin.com/in/expertname",
"https://twitter.com/expertname"
]
},
"publisher": {
"@type": "Organization",
"name": "Company Name",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
}
}
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Company Name",
"url": "https://example.com",
"logo": "https://example.com/logo.png",
"description": "Brief description of what the organization does",
"foundingDate": "2010",
"sameAs": [
"https://www.linkedin.com/company/companyname",
"https://twitter.com/companyname",
"https://github.com/companyname"
],
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+1-555-123-4567",
"contactType": "customer service",
"availableLanguage": ["English", "German"]
}
}
AI 系统优先考虑来自可信来源的内容。实施以下信号:
<article>
<!-- Content -->
<footer class="author-bio">
<img src="/authors/jane-doe.jpg" alt="Jane Doe" />
<div class="author-info">
<h4>About the Author</h4>
<p class="author-name">Jane Doe, PhD</p>
<p class="author-credentials">
15 years of experience in digital marketing.
Former Head of SEO at Fortune 500 company.
Published in Search Engine Journal, Moz, and Ahrefs Blog.
</p>
<ul class="author-links">
<li><a href="https://linkedin.com/in/janedoe" rel="author">LinkedIn</a></li>
<li><a href="https://twitter.com/janedoe" rel="author">Twitter</a></li>
</ul>
</div>
</footer>
</article>
| 平台 | 新鲜度偏好 | 建议更新周期 |
|---|---|---|
| Perplexity AI | 非常高 | 热门话题每 2-3 天更新 |
| ChatGPT 搜索 | 高 | 每周更新 |
| Google AI Overviews | 中等 | 每月刷新 |
| Bing Copilot | 中等 | 每月刷新 |
## 内容新鲜度检查清单
### 每周任务
- [ ] 使用最新数据更新统计数据
- [ ] 刷新截图和示例
- [ ] 添加新的进展或新闻
- [ ] 更新"最后修改"时间戳
### 每月任务
- [ ] 审查并更新所有事实性陈述
- [ ] 为新兴主题添加新章节
- [ ] 更新失效链接
- [ ] 刷新专家引述
### 每季度任务
- [ ] 全面的内容审计
- [ ] 竞争分析
- [ ] 根据查询趋势调整结构
- [ ] 更新所有 Schema 标记
<article>
<header>
<h1>Article Title</h1>
<div class="article-meta">
<time datetime="2025-01-15" itemprop="datePublished">
Published: January 15, 2025
</time>
<time datetime="2025-01-15" itemprop="dateModified">
Last Updated: January 15, 2025
</time>
</div>
</header>
<!-- Content -->
</article>
为了被 AI 搜索引擎索引,请明确允许其爬虫:
# robots.txt - AI Search Optimization
# Standard search engines
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
# OpenAI (ChatGPT)
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
# Perplexity AI
User-agent: PerplexityBot
Allow: /
# Anthropic (Claude)
User-agent: ClaudeBot
Allow: /
User-agent: anthropic-ai
Allow: /
# Google AI (Gemini)
User-agent: Google-Extended
Allow: /
# Meta AI
User-agent: FacebookBot
Allow: /
# Common Crawl (used by many AI systems)
User-agent: CCBot
Allow: /
# Microsoft/Bing AI
User-agent: Applebot
Allow: /
# Default rule
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /private/
# Sitemap
Sitemap: https://example.com/sitemap.xml
一些组织希望在 AI 搜索结果中被引用,但不希望其内容用于训练 AI 模型。方法如下:
理解区别:
| 机器人 | 作用 | 阻止 = |
|---|---|---|
GPTBot | 为训练 OpenAI 模型而爬取 | 您的内容不会用于训练未来的 GPT 版本 |
ChatGPT-User | 用户搜索时的实时浏览 | ChatGPT 无法在实时答案中引用您 |
Google-Extended | 为训练 Gemini AI 而爬取 | 您的内容不会用于训练 Gemini |
PerplexityBot | Perplexity 答案的实时搜索 | Perplexity 无法引用您 |
CCBot | Common Crawl - 公开的训练数据集 | 您的内容不会出现在公共 AI 训练数据中 |
示例:阻止训练,允许实时搜索引用:
# BLOCK: AI model training (your content won't train future AI)
User-agent: GPTBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: CCBot
Disallow: /
# ALLOW: Real-time AI search (AI can cite you in answers)
User-agent: ChatGPT-User
Allow: /
User-agent: PerplexityBot
Allow: /
注意: 大多数专注于 AI 搜索可见性的企业应允许所有机器人(上文第 6 节)。仅当您对 AI 使用您的内容进行训练有特定顾虑时,才使用此方法。
| 机器人名称 | 公司 | 目的 |
|---|---|---|
| GPTBot | OpenAI | 训练数据 & ChatGPT 浏览 |
| ChatGPT-User | OpenAI | ChatGPT 网页浏览 |
| PerplexityBot | Perplexity | 实时搜索 & 引用 |
| ClaudeBot | Anthropic | 训练 & 检索 |
| anthropic-ai | Anthropic | Claude AI 训练 |
| Google-Extended | Gemini AI 训练 | |
| FacebookBot | Meta | Meta AI 训练 |
| CCBot | Common Crawl | AI 训练的开放数据集 |
AI 搜索偏爱自然语言:
传统关键词: "best project management software"
对话式查询:
## What is [Topic]?
[Topic] is [direct definition in 1-2 sentences].
### Key characteristics:
- Characteristic 1
- Characteristic 2
- Characteristic 3
## How does [Topic] work?
[Clear explanation of process]
### Step-by-step breakdown:
1. First step
2. Second step
3. Third step
## Why is [Topic] important?
[2-3 sentences on significance]
### Benefits include:
- Benefit 1 with specific outcome
- Benefit 2 with measurable result
- Benefit 3 with real-world application
<section class="faq">
<h2>Frequently Asked Questions</h2>
<details>
<summary>What is Answer Engine Optimization?</summary>
<p>Answer Engine Optimization (AEO) is the practice of...</p>
</details>
<details>
<summary>How is GEO different from traditional SEO?</summary>
<p>While traditional SEO focuses on...</p>
</details>
<details>
<summary>Which AI search platforms should I optimize for?</summary>
<p>The main platforms to consider are...</p>
</details>
</section>
Perplexity 和其他 AI 引擎偏爱视觉内容:
<figure>
<img
src="/images/ai-search-diagram.webp"
alt="Diagram showing how AI search engines process and cite content"
width="800"
height="450"
loading="lazy"
/>
<figcaption>
How AI search engines extract and cite content sources
</figcaption>
</figure>
最佳实践:
<figure class="video-embed">
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
title="Detailed explanation of AI Search Optimization"
allow="accelerometer; autoplay; clipboard-write; encrypted-media"
allowfullscreen
></iframe>
<figcaption>
Video: Complete guide to optimizing for AI search engines
</figcaption>
</figure>
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "AI Search Optimization Tutorial",
"description": "Learn how to optimize content for ChatGPT, Perplexity, and Google AI",
"thumbnailUrl": "https://example.com/video-thumbnail.jpg",
"uploadDate": "2025-01-15",
"duration": "PT10M30S",
"contentUrl": "https://example.com/videos/ai-search-tutorial.mp4"
}
| 工具 | 监控的平台 | 关键功能 |
|---|---|---|
| Semrush AI Visibility | ChatGPT, Gemini, Perplexity | 免费层级,提及跟踪 |
| Brand24 | ChatGPT, Perplexity, Claude, Gemini | 多平台分析 |
| SE Ranking | Google AI Overviews, ChatGPT, Gemini | 声量份额跟踪 |
| Keyword.com | Google AI Overviews, ChatGPT, Perplexity | 优化建议 |
| BrandBeacon.ai | ChatGPT, Perplexity | 竞争对手基准测试 |
| Sight AI | ChatGPT, Claude, Perplexity | 情感分析 |
## 月度 AI 可见性审计
### 测试查询(根据您的领域调整)
1. "What is [your product/service]?"
2. "Best [your category] in [year]"
3. "[Your brand] vs [competitor]"
4. "How to [task your product solves]"
5. "[Your expertise area] best practices"
### 要测试的平台
- [ ] ChatGPT (chat.openai.com)
- [ ] Perplexity (perplexity.ai)
- [ ] Google (check for AI Overviews)
- [ ] Microsoft Copilot (copilot.microsoft.com)
- [ ] Claude (claude.ai)
### 为每个查询记录
- 您被引用了吗?(是/否)
- 引用上下文(正面/中性/负面)
- 提及的竞争对手
- 信息准确性
- 建议的改进
## 季度审查检查清单
### AI 平台更新
- [ ] 审查主要平台的新 AI 搜索功能
- [ ] 为新的 AI 机器人用户代理更新 robots.txt
- [ ] 在新兴/新兴 AI 平台上测试可见性
### 内容策略
- [ ] 分析哪些内容类型获得最多引用
- [ ] 识别 AI 覆盖范围与竞争对手的差距
- [ ] 为服务不足的查询规划新内容
### 技术更新
- [ ] 审查 schema.org 以获取新的相关类型
- [ ] 更新结构化数据实现
- [ ] 测试页面速度和核心网页指标
兼容性: TYPO3 v14.x 本节中的所有配置均适用于 TYPO3 v14。
本节涵盖使用 TYPO3 扩展、配置和最佳实践来具体实施 AEO/GEO 策略。
⚠️ 强烈推荐 Composer 模式
对于 AI 搜索优化,强烈推荐基于 Composer 的 TYPO3 安装。本指南中的所有扩展均可通过 Composer(Packagist)和 TER(经典模式)获得。
| 方面 | Composer 模式 | 经典模式 |
|---|---|---|
| 依赖项解析 | 自动,带版本约束 | 手动,无传递性依赖 |
| 自动加载 | PSR-4 优化,生产就绪 | TYPO3 内部,优化较少 |
| 安全性 | 独立的 Web 根目录(/public) | 所有文件都在 Web 根目录中 |
| 更新 | 单一命令:composer update | 每个扩展手动下载/上传 |
| 可重现性 | composer.lock 确保安装一致 | 无版本锁定机制 |
| TYPO3 v14 未来 | 完全支持 | 所有扩展都需要 composer.json |
Composer 模式 使用 PHP 的标准依赖管理器来:
brotkrueml/schema 这样的扩展依赖于 psr/http-message 和其他包。Composer 解析整个依赖树,确保安装兼容的版本。composer.json 中的约束 "typo3/cms-core": "^14.0" 确保仅安装兼容的版本。vendor/、config/ 和其他敏感目录放在 Web 可访问的 /public 文件夹之外。TYPO3 v14 重大变更: 在 TYPO3 v14 中,即使是经典模式也要求每个扩展都有一个有效的 composer.json,并带有正确的 type 和 extension-key 定义。没有此文件的扩展将不会被检测到。
// 所有扩展(v14+)所需的 composer.json 结构
{
"name": "vendor/extension-key",
"type": "typo3-cms-extension",
"extra": {
"typo3/cms": {
"extension-key": "extension_key"
}
}
}
| 扩展 | TYPO3 v14 | PHP | Composer | TER | 目的 |
|---|---|---|---|---|---|
typo3/cms-seo | ✓ | 8.2+ | ✓ | ✓ | 核心 SEO(元标签、站点地图、规范链接) |
brotkrueml/schema | ✓(在 Packagist 上验证 v4.x) | 8.2+ | ✓ | ✓ | Schema.org 结构化数据(JSON-LD) |
clickstorm/cs_seo | ✓(在 Packagist 上验证 v9.3+) | 8.2+ | ✓ | ✓ | 扩展的 SEO 功能、评估 |
其他 SEO 扩展(例如 Yoast)可能落后于核心 - 安装前请务必检查
require.typo3/cms-core。
# Core SEO extension (meta tags, sitemaps, canonicals)
ddev composer require typo3/cms-seo
# Schema.org structured data (essential for AI search)
# Version constraint ensures TYPO3 v14 compatibility
ddev composer require brotkrueml/schema:"^4.2"
# Optional: Extended SEO features (TYPO3 v14)
ddev composer require clickstorm/cs_seo:"^9.3"
# In Composer mode, extensions are auto-activated
# Verify installation:
ddev typo3 extension:list | grep -E "seo|schema"
版本约束说明:
{
"require": {
"typo3/cms-seo": "^14.0",
"brotkrueml/schema": "^4.2"
}
}
^4.2 = 任何版本 ≥4.2.0 且 <5.0.0(允许次要/补丁更新)typo3/cms-seo 的 ^14.0 = 仅限 TYPO3 v14 系列(本集合的目标)注意: 支持经典模式,但不推荐。TYPO3 v14 要求所有扩展即使在经典模式下也拥有有效的
composer.json。
通过 TYPO3 的静态路由配置 robots.txt 以允许 AI 爬虫:
# config/sites/main/config.yaml
routes:
- route: robots.txt
type: staticText
content: |
# Standard search engines
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
# OpenAI (ChatGPT)
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
# Perplexity AI
User-agent: PerplexityBot
Allow: /
# Anthropic (Claude)
User-agent: ClaudeBot
Allow: /
User-agent: anthropic-ai
Allow: /
# Google AI (Gemini)
User-agent: Google-Extended
Allow: /
# Meta AI
User-agent: FacebookBot
Allow: /
# Common Crawl (used by many AI systems)
User-agent: CCBot
Allow: /
# Default
User-agent: *
Allow: /
Disallow: /typo3/
Disallow: /typo3conf/
Disallow: /typo3temp/
Sitemap: https://example.com/sitemap.xml
ddev composer require brotkrueml/schema:"^4.2"
ddev typo3 extension:setup -e schema
在您的站点包中包含静态 TypoScript 模板。
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<schema:type.fAQPage>
<f:for each="{faqItems}" as="faq">
<schema:type.question -as="mainEntity" name="{faq.question}">
<schema:type.answer -as="acceptedAnswer" text="{faq.answer}" />
</schema:type.question>
</f:for>
</schema:type.fAQPage>
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<schema:type.article
-id="https://example.com/article/{article.uid}"
headline="{article.title}"
description="{article.teaser}"
datePublished="{article.crdate -> f:format.date(format: 'c')}"
dateModified="{article.tstamp -> f:format.date(format: 'c')}"
>
<schema:type.person -as="author"
name="{article.author.name}"
url="{article.author.profileUrl}"
>
<schema:property -as="sameAs" value="{article.author.linkedIn}" />
<schema:property -as="sameAs" value="{article.author.twitter}" />
</schema:type.person>
<schema:type.organization -as="publisher"
name="{settings.siteName}"
url="{settings.siteUrl}"
>
<schema:type.imageObject -as="logo" url="{settings.logoUrl}" />
</schema:type.organization>
</schema:type.article>
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<schema:type.howTo
name="How to Optimize Content for AI Search"
description="Step-by-step guide to improving visibility in AI-powered search engines"
>
<f:for each="{steps}" as="step" iteration="iter">
<schema:type.howToStep -as="step"
name="{step.title}"
text="{step.description}"
position="{iter.cycle}"
/>
</f:for>
</schema:type.howTo>
<?php
declare(strict_types=1);
namespace Vendor\SitePackage\EventListener;
use Brotkrueml\Schema\Event\RenderAdditionalTypesEvent;
use Brotkrueml\Schema\Type\TypeFactory;
use TYPO3\CMS\Core\Attribute\AsEventListener;
#[AsEventListener(identifier: 'site-package/add-organization-schema')]
final readonly class AddOrganizationSchema
{
public function __construct(
private TypeFactory $typeFactory,
) {}
public function __invoke(RenderAdditionalTypesEvent $event): void
Scope: Optimizing content for AI-powered search engines and answer engines This skill covers strategies for visibility in ChatGPT, Perplexity, Google AI Overviews, Microsoft Copilot, and other generative AI platforms.
Answer Engine Optimization focuses on structuring content to provide direct, concise answers to user queries through AI-powered platforms. Unlike traditional SEO which aims for link clicks, AEO optimizes for being cited as the answer source.
Target platforms:
Generative Engine Optimization is the broader discipline of enhancing content visibility within AI-generated search results. It targets generative engines that synthesize answers from multiple sources rather than presenting traditional link lists.
Key differences from traditional SEO:
| Aspect | Traditional SEO | AEO/GEO |
|---|---|---|
| Goal | Rank in SERPs | Be cited in AI answers |
| User behavior | Click through to site | Get answer directly |
| Content format | Keyword-optimized pages | Structured, citable content |
| Success metric | Click-through rate | Citation frequency |
| Query type | Short keywords | Conversational, long-tail |
AI systems extract information more effectively from well-structured content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Descriptive, Question-Answering Title</title>
</head>
<body>
<article>
<header>
<h1>Primary Topic as Question or Clear Statement</h1>
<p class="summary">Direct 2-3 sentence answer to the main question.</p>
</header>
<main>
<section>
<h2>Subtopic Heading</h2>
<p>Detailed explanation with facts and data.</p>
<ul>
<li>Key point 1 with specific information</li>
<li>Key point 2 with verifiable data</li>
<li>Key point 3 with actionable insight</li>
</ul>
</section>
</main>
<aside>
<h3>Quick Facts</h3>
<dl>
<dt>Term</dt>
<dd>Definition</dd>
</dl>
</aside>
</article>
</body>
</html>
# H1: Main Topic (contains primary question/keyword)
└── ## H2: Major subtopic
└── ### H3: Specific aspect
└── #### H4: Details (use sparingly)
Rules:
Structure content for AI extraction:
┌─────────────────────────────────────┐
│ DIRECT ANSWER (First 1-2 │ ← AI extracts this
│ sentences answer the query) │
├─────────────────────────────────────┤
│ KEY FACTS & CONTEXT │ ← Supporting evidence
│ (Bullet points, data, quotes) │
├─────────────────────────────────────┤
│ DETAILED EXPLANATION │ ← Comprehensive coverage
│ (Background, methodology, │
│ examples, case studies) │
├─────────────────────────────────────┤
│ RELATED TOPICS │ ← Topic authority signals
│ (Links to related content) │
└─────────────────────────────────────┘
AI engines prefer structured data formats:
<!-- Comparison Table -->
<table>
<caption>Feature Comparison: Product A vs Product B</caption>
<thead>
<tr>
<th>Feature</th>
<th>Product A</th>
<th>Product B</th>
</tr>
</thead>
<tbody>
<tr>
<td>Price</td>
<td>$99/month</td>
<td>$149/month</td>
</tr>
<!-- More rows -->
</tbody>
</table>
<!-- Definition List for Terms -->
<dl>
<dt>AEO</dt>
<dd>Answer Engine Optimization - optimizing content for direct answers</dd>
<dt>GEO</dt>
<dd>Generative Engine Optimization - visibility in AI-generated results</dd>
</dl>
<!-- Step-by-Step Process -->
<ol>
<li>Step one with clear action</li>
<li>Step two with measurable outcome</li>
<li>Step three with verification method</li>
</ol>
Research shows structured data significantly improves AI search visibility:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is Answer Engine Optimization?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Answer Engine Optimization (AEO) is a strategic approach to structuring content so AI platforms like ChatGPT, Perplexity, and Google AI Overviews can easily extract and cite it as direct answers to user queries."
}
},
{
"@type": "Question",
"name": "How is AEO different from SEO?",
"acceptedAnswer": {
"@type": "Answer",
"text": "While SEO focuses on ranking in traditional search results for clicks, AEO optimizes content to be cited directly in AI-generated answers, often resulting in zero-click interactions where users get information without visiting the source."
}
}
]
}
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to Optimize Content for AI Search",
"description": "Step-by-step guide to improving visibility in AI-powered search engines",
"totalTime": "PT30M",
"step": [
{
"@type": "HowToStep",
"name": "Structure Content Semantically",
"text": "Use proper HTML5 semantic elements like article, section, and aside",
"position": 1
},
{
"@type": "HowToStep",
"name": "Implement Schema Markup",
"text": "Add FAQPage, HowTo, and Article schema to your pages",
"position": 2
},
{
"@type": "HowToStep",
"name": "Optimize for Conversational Queries",
"text": "Write content that answers natural language questions",
"position": 3
}
]
}
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Complete Guide to AI Search Optimization",
"description": "Learn how to optimize content for ChatGPT, Perplexity, and Google AI Overviews",
"datePublished": "2025-01-15",
"dateModified": "2025-01-15",
"author": {
"@type": "Person",
"name": "Expert Name",
"url": "https://example.com/about/expert-name",
"jobTitle": "SEO Specialist",
"sameAs": [
"https://linkedin.com/in/expertname",
"https://twitter.com/expertname"
]
},
"publisher": {
"@type": "Organization",
"name": "Company Name",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
}
}
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Company Name",
"url": "https://example.com",
"logo": "https://example.com/logo.png",
"description": "Brief description of what the organization does",
"foundingDate": "2010",
"sameAs": [
"https://www.linkedin.com/company/companyname",
"https://twitter.com/companyname",
"https://github.com/companyname"
],
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+1-555-123-4567",
"contactType": "customer service",
"availableLanguage": ["English", "German"]
}
}
AI systems prioritize content from credible sources. Implement these signals:
<article>
<!-- Content -->
<footer class="author-bio">
<img src="/authors/jane-doe.jpg" alt="Jane Doe" />
<div class="author-info">
<h4>About the Author</h4>
<p class="author-name">Jane Doe, PhD</p>
<p class="author-credentials">
15 years of experience in digital marketing.
Former Head of SEO at Fortune 500 company.
Published in Search Engine Journal, Moz, and Ahrefs Blog.
</p>
<ul class="author-links">
<li><a href="https://linkedin.com/in/janedoe" rel="author">LinkedIn</a></li>
<li><a href="https://twitter.com/janedoe" rel="author">Twitter</a></li>
</ul>
</div>
</footer>
</article>
| Platform | Freshness Preference | Recommended Update Cycle |
|---|---|---|
| Perplexity AI | Very high | Every 2-3 days for trending topics |
| ChatGPT Search | High | Weekly updates |
| Google AI Overviews | Moderate | Monthly refresh |
| Bing Copilot | Moderate | Monthly refresh |
## Content Freshness Checklist
### Weekly Tasks
- [ ] Update statistics with latest data
- [ ] Refresh screenshots and examples
- [ ] Add new developments or news
- [ ] Update "Last modified" timestamp
### Monthly Tasks
- [ ] Review and update all factual claims
- [ ] Add new sections for emerging topics
- [ ] Update broken links
- [ ] Refresh expert quotes
### Quarterly Tasks
- [ ] Comprehensive content audit
- [ ] Competitive analysis
- [ ] Restructure based on query trends
- [ ] Update all schema markup
<article>
<header>
<h1>Article Title</h1>
<div class="article-meta">
<time datetime="2025-01-15" itemprop="datePublished">
Published: January 15, 2025
</time>
<time datetime="2025-01-15" itemprop="dateModified">
Last Updated: January 15, 2025
</time>
</div>
</header>
<!-- Content -->
</article>
To be indexed by AI search engines, explicitly allow their crawlers:
# robots.txt - AI Search Optimization
# Standard search engines
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
# OpenAI (ChatGPT)
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
# Perplexity AI
User-agent: PerplexityBot
Allow: /
# Anthropic (Claude)
User-agent: ClaudeBot
Allow: /
User-agent: anthropic-ai
Allow: /
# Google AI (Gemini)
User-agent: Google-Extended
Allow: /
# Meta AI
User-agent: FacebookBot
Allow: /
# Common Crawl (used by many AI systems)
User-agent: CCBot
Allow: /
# Microsoft/Bing AI
User-agent: Applebot
Allow: /
# Default rule
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /private/
# Sitemap
Sitemap: https://example.com/sitemap.xml
Some organizations want to be cited in AI search results but don't want their content used to train AI models. Here's how:
Understanding the difference:
| Bot | What it does | Block = |
|---|---|---|
GPTBot | Crawls for training OpenAI models | Your content won't train future GPT versions |
ChatGPT-User | Live browsing when users search | ChatGPT can't cite you in real-time answers |
Google-Extended | Crawls for training Gemini AI | Your content won't train Gemini |
PerplexityBot | Live search for Perplexity answers | Perplexity can't cite you |
Example: Block training, allow live search citations:
# BLOCK: AI model training (your content won't train future AI)
User-agent: GPTBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: CCBot
Disallow: /
# ALLOW: Real-time AI search (AI can cite you in answers)
User-agent: ChatGPT-User
Allow: /
User-agent: PerplexityBot
Allow: /
Note: Most businesses focused on AI search visibility should allow all bots (Section 6 above). Only use this approach if you have specific concerns about AI training on your content.
| Bot Name | Company | Purpose |
|---|---|---|
| GPTBot | OpenAI | Training data & ChatGPT browsing |
| ChatGPT-User | OpenAI | ChatGPT web browsing |
| PerplexityBot | Perplexity | Real-time search & citations |
| ClaudeBot | Anthropic | Training & retrieval |
| anthropic-ai | Anthropic | Claude AI training |
| Google-Extended | Gemini AI training | |
| FacebookBot | Meta | Meta AI training |
| CCBot | Common Crawl | Open dataset for AI training |
AI search favors natural language:
Traditional keyword: "best project management software"
Conversational queries:
## What is [Topic]?
[Topic] is [direct definition in 1-2 sentences].
### Key characteristics:
- Characteristic 1
- Characteristic 2
- Characteristic 3
## How does [Topic] work?
[Clear explanation of process]
### Step-by-step breakdown:
1. First step
2. Second step
3. Third step
## Why is [Topic] important?
[2-3 sentences on significance]
### Benefits include:
- Benefit 1 with specific outcome
- Benefit 2 with measurable result
- Benefit 3 with real-world application
<section class="faq">
<h2>Frequently Asked Questions</h2>
<details>
<summary>What is Answer Engine Optimization?</summary>
<p>Answer Engine Optimization (AEO) is the practice of...</p>
</details>
<details>
<summary>How is GEO different from traditional SEO?</summary>
<p>While traditional SEO focuses on...</p>
</details>
<details>
<summary>Which AI search platforms should I optimize for?</summary>
<p>The main platforms to consider are...</p>
</details>
</section>
Perplexity and other AI engines prefer visual content:
<figure>
<img
src="/images/ai-search-diagram.webp"
alt="Diagram showing how AI search engines process and cite content"
width="800"
height="450"
loading="lazy"
/>
<figcaption>
How AI search engines extract and cite content sources
</figcaption>
</figure>
Best practices:
<figure class="video-embed">
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
title="Detailed explanation of AI Search Optimization"
allow="accelerometer; autoplay; clipboard-write; encrypted-media"
allowfullscreen
></iframe>
<figcaption>
Video: Complete guide to optimizing for AI search engines
</figcaption>
</figure>
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "AI Search Optimization Tutorial",
"description": "Learn how to optimize content for ChatGPT, Perplexity, and Google AI",
"thumbnailUrl": "https://example.com/video-thumbnail.jpg",
"uploadDate": "2025-01-15",
"duration": "PT10M30S",
"contentUrl": "https://example.com/videos/ai-search-tutorial.mp4"
}
| Tool | Platforms Monitored | Key Features |
|---|---|---|
| Semrush AI Visibility | ChatGPT, Gemini, Perplexity | Free tier, mention tracking |
| Brand24 | ChatGPT, Perplexity, Claude, Gemini | Multi-platform analysis |
| SE Ranking | Google AI Overviews, ChatGPT, Gemini | Share of voice tracking |
| Keyword.com | Google AI Overviews, ChatGPT, Perplexity | Optimization suggestions |
| BrandBeacon.ai | ChatGPT, Perplexity | Competitor benchmarking |
| Sight AI | ChatGPT, Claude, Perplexity | Sentiment analysis |
## Monthly AI Visibility Audit
### Test Queries (adapt to your niche)
1. "What is [your product/service]?"
2. "Best [your category] in [year]"
3. "[Your brand] vs [competitor]"
4. "How to [task your product solves]"
5. "[Your expertise area] best practices"
### Platforms to Test
- [ ] ChatGPT (chat.openai.com)
- [ ] Perplexity (perplexity.ai)
- [ ] Google (check for AI Overviews)
- [ ] Microsoft Copilot (copilot.microsoft.com)
- [ ] Claude (claude.ai)
### Record for Each Query
- Were you cited? (Yes/No)
- Citation context (positive/neutral/negative)
- Competitors mentioned
- Information accuracy
- Suggested improvements
## Quarterly Review Checklist
### AI Platform Updates
- [ ] Review new AI search features from major platforms
- [ ] Update robots.txt for new AI bot user agents
- [ ] Test visibility on new/emerging AI platforms
### Content Strategy
- [ ] Analyze which content types get most citations
- [ ] Identify gaps in AI coverage vs competitors
- [ ] Plan new content for underserved queries
### Technical Updates
- [ ] Review schema.org for new relevant types
- [ ] Update structured data implementation
- [ ] Test page speed and Core Web Vitals
Compatibility: TYPO3 v14.x All configurations in this section work on TYPO3 v14.
This section covers TYPO3-specific implementation of AEO/GEO strategies using TYPO3 extensions, configuration, and best practices.
⚠️ Composer Mode Highly Recommended
For AI search optimization, Composer-based TYPO3 installations are strongly recommended. All extensions in this guide are available via both Composer (Packagist) and TER (Classic Mode).
| Aspect | Composer Mode | Classic Mode |
|---|---|---|
| Dependency Resolution | Automatic with version constraints | Manual, no transitive dependencies |
| Autoloading | PSR-4 optimized, production-ready | TYPO3 internal, less optimized |
| Security | Separate web root (/public) | All files in web root |
| Updates | Single command: composer update | Manual download/upload per extension |
| Reproducibility | composer.lock ensures identical installs | No version locking mechanism |
Composer Mode uses PHP's standard dependency manager to:
Resolve Dependencies Automatically : Extensions like brotkrueml/schema depend on psr/http-message and other packages. Composer resolves the entire dependency tree, ensuring compatible versions are installed.
Generate Optimized Autoloaders : Composer creates a PSR-4 compliant autoloader that loads classes on-demand, improving performance compared to TYPO3's legacy class loading.
Enforce Version Constraints : The composer.json constraint "typo3/cms-core": "^14.0" guarantees only compatible versions are installed.
Enable Security Isolation : The recommended structure places vendor/, config/, and other sensitive directories outside the web-accessible /public folder.
TYPO3 v14 Breaking Change : In TYPO3 v14, even Classic Mode requires every extension to have a valid composer.json with proper type and extension-key definitions. Extensions without this file will not be detected.
// Required composer.json structure for all extensions (v14+)
{
"name": "vendor/extension-key",
"type": "typo3-cms-extension",
"extra": {
"typo3/cms": {
"extension-key": "extension_key"
}
}
}
| Extension | TYPO3 v14 | PHP | Composer | TER | Purpose |
|---|---|---|---|---|---|
typo3/cms-seo | ✓ | 8.2+ | ✓ | ✓ | Core SEO (meta tags, sitemaps, canonicals) |
brotkrueml/schema | ✓ (verify v4.x on Packagist) | 8.2+ | ✓ | ✓ | Schema.org structured data (JSON-LD) |
clickstorm/cs_seo | ✓ (verify v9.3+ on Packagist) | 8.2+ | ✓ | ✓ | Extended SEO features, evaluations |
Other SEO extensions (e.g. Yoast) may lag Core — always check
require.typo3/cms-corebefore installing.
# Core SEO extension (meta tags, sitemaps, canonicals)
ddev composer require typo3/cms-seo
# Schema.org structured data (essential for AI search)
# Version constraint ensures TYPO3 v14 compatibility
ddev composer require brotkrueml/schema:"^4.2"
# Optional: Extended SEO features (TYPO3 v14)
ddev composer require clickstorm/cs_seo:"^9.3"
# In Composer mode, extensions are auto-activated
# Verify installation:
ddev typo3 extension:list | grep -E "seo|schema"
Version Constraints Explained:
{
"require": {
"typo3/cms-seo": "^14.0",
"brotkrueml/schema": "^4.2"
}
}
^4.2 = Any version ≥4.2.0 and <5.0.0 (allows minor/patch updates)^14.0 for typo3/cms-seo = TYPO3 v14 line only (this collection’s target)Note: Classic Mode is supported but not recommended. TYPO3 v14 requires all extensions to have a valid
composer.jsoneven in Classic Mode.
Download from TER:
Install via Extension Manager:
Verify Installation:
Configure robots.txt via TYPO3's static routes to allow AI crawlers:
# config/sites/main/config.yaml
routes:
- route: robots.txt
type: staticText
content: |
# Standard search engines
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
# OpenAI (ChatGPT)
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
# Perplexity AI
User-agent: PerplexityBot
Allow: /
# Anthropic (Claude)
User-agent: ClaudeBot
Allow: /
User-agent: anthropic-ai
Allow: /
# Google AI (Gemini)
User-agent: Google-Extended
Allow: /
# Meta AI
User-agent: FacebookBot
Allow: /
# Common Crawl (used by many AI systems)
User-agent: CCBot
Allow: /
# Default
User-agent: *
Allow: /
Disallow: /typo3/
Disallow: /typo3conf/
Disallow: /typo3temp/
Sitemap: https://example.com/sitemap.xml
ddev composer require brotkrueml/schema:"^4.2"
ddev typo3 extension:setup -e schema
Include the static TypoScript template in your site package.
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<schema:type.fAQPage>
<f:for each="{faqItems}" as="faq">
<schema:type.question -as="mainEntity" name="{faq.question}">
<schema:type.answer -as="acceptedAnswer" text="{faq.answer}" />
</schema:type.question>
</f:for>
</schema:type.fAQPage>
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<schema:type.article
-id="https://example.com/article/{article.uid}"
headline="{article.title}"
description="{article.teaser}"
datePublished="{article.crdate -> f:format.date(format: 'c')}"
dateModified="{article.tstamp -> f:format.date(format: 'c')}"
>
<schema:type.person -as="author"
name="{article.author.name}"
url="{article.author.profileUrl}"
>
<schema:property -as="sameAs" value="{article.author.linkedIn}" />
<schema:property -as="sameAs" value="{article.author.twitter}" />
</schema:type.person>
<schema:type.organization -as="publisher"
name="{settings.siteName}"
url="{settings.siteUrl}"
>
<schema:type.imageObject -as="logo" url="{settings.logoUrl}" />
</schema:type.organization>
</schema:type.article>
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<schema:type.howTo
name="How to Optimize Content for AI Search"
description="Step-by-step guide to improving visibility in AI-powered search engines"
>
<f:for each="{steps}" as="step" iteration="iter">
<schema:type.howToStep -as="step"
name="{step.title}"
text="{step.description}"
position="{iter.cycle}"
/>
</f:for>
</schema:type.howTo>
<?php
declare(strict_types=1);
namespace Vendor\SitePackage\EventListener;
use Brotkrueml\Schema\Event\RenderAdditionalTypesEvent;
use Brotkrueml\Schema\Type\TypeFactory;
use TYPO3\CMS\Core\Attribute\AsEventListener;
#[AsEventListener(identifier: 'site-package/add-organization-schema')]
final readonly class AddOrganizationSchema
{
public function __construct(
private TypeFactory $typeFactory,
) {}
public function __invoke(RenderAdditionalTypesEvent $event): void
{
$organization = $this->typeFactory->create('Organization')
->setProperty('name', 'Your Company Name')
->setProperty('url', 'https://example.com')
->setProperty('logo', 'https://example.com/logo.png')
->setProperty('description', 'Brief company description for AI understanding')
->setProperty('sameAs', [
'https://www.linkedin.com/company/yourcompany',
'https://twitter.com/yourcompany',
'https://github.com/yourcompany',
]);
$contactPoint = $this->typeFactory->create('ContactPoint')
->setProperty('telephone', '+43-1-234567')
->setProperty('contactType', 'customer service')
->setProperty('availableLanguage', ['German', 'English']);
$organization->setProperty('contactPoint', $contactPoint);
$event->addType($organization);
}
}
<?php
declare(strict_types=1);
namespace Vendor\SitePackage\EventListener;
use Brotkrueml\Schema\Event\RenderAdditionalTypesEvent;
use Brotkrueml\Schema\Type\TypeFactory;
use TYPO3\CMS\Core\Attribute\AsEventListener;
#[AsEventListener(identifier: 'site-package/add-article-schema')]
final readonly class AddArticleSchema
{
public function __construct(
private TypeFactory $typeFactory,
) {}
public function __invoke(RenderAdditionalTypesEvent $event): void
{
$request = $event->getRequest();
$pageInformation = $request->getAttribute('frontend.page.information');
$page = $pageInformation->getPageRecord();
// Only add Article schema for specific doktypes (e.g., 1 = standard page)
if ((int)$page['doktype'] !== 1) {
return;
}
$article = $this->typeFactory->create('Article')
->setProperty('headline', $page['title'])
->setProperty('description', $page['description'] ?: $page['abstract'])
->setProperty('datePublished', date('c', $page['crdate']))
->setProperty('dateModified', date('c', $page['tstamp']));
// Add author if available
if (!empty($page['author'])) {
$author = $this->typeFactory->create('Person')
->setProperty('name', $page['author']);
$article->setProperty('author', $author);
}
$event->addType($article);
}
}
# Expose last modified date in HTTP headers
config {
sendCacheHeaders = 1
additionalHeaders {
10 {
header = X-Content-Last-Modified
value = TEXT
value.data = page:SYS_LASTCHANGED
value.strftime = %Y-%m-%dT%H:%M:%S%z
}
}
}
# Display last updated date in content
lib.lastModified = TEXT
lib.lastModified {
data = page:SYS_LASTCHANGED
strftime = %B %d, %Y
wrap = <time datetime="|" itemprop="dateModified">Last updated: |</time>
}
<article itemscope itemtype="https://schema.org/Article">
<header>
<h1 itemprop="headline">{page.title}</h1>
<div class="article-meta">
<time datetime="{page.crdate -> f:format.date(format: 'c')}" itemprop="datePublished">
Published: <f:format.date format="F j, Y">{page.crdate}</f:format.date>
</time>
<time datetime="{page.SYS_LASTCHANGED -> f:format.date(format: 'c')}" itemprop="dateModified">
Last Updated: <f:format.date format="F j, Y">{page.SYS_LASTCHANGED}</f:format.date>
</time>
</div>
</header>
<!-- Content -->
</article>
<?php
// Configuration/TCA/Overrides/pages.php
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
$additionalColumns = [
'tx_sitepackage_author_name' => [
'label' => 'Author Name',
'config' => [
'type' => 'input',
'size' => 50,
'max' => 255,
],
],
'tx_sitepackage_author_title' => [
'label' => 'Author Title/Credentials',
'config' => [
'type' => 'input',
'size' => 50,
'max' => 255,
],
],
'tx_sitepackage_author_bio' => [
'label' => 'Author Bio',
'config' => [
'type' => 'text',
'rows' => 5,
],
],
'tx_sitepackage_author_linkedin' => [
'label' => 'Author LinkedIn URL',
'config' => [
'type' => 'link',
'allowedTypes' => ['url'],
],
],
];
ExtensionManagementUtility::addTCAcolumns('pages', $additionalColumns);
ExtensionManagementUtility::addToAllTCAtypes(
'pages',
'--div--;Author,tx_sitepackage_author_name,tx_sitepackage_author_title,tx_sitepackage_author_bio,tx_sitepackage_author_linkedin'
);
<?php
declare(strict_types=1);
namespace Vendor\SitePackage\EventListener;
use Brotkrueml\Schema\Event\RenderAdditionalTypesEvent;
use Brotkrueml\Schema\Type\TypeFactory;
use TYPO3\CMS\Core\Attribute\AsEventListener;
#[AsEventListener(identifier: 'site-package/add-author-schema')]
final readonly class AddAuthorSchema
{
public function __construct(
private TypeFactory $typeFactory,
) {}
public function __invoke(RenderAdditionalTypesEvent $event): void
{
$request = $event->getRequest();
$pageInformation = $request->getAttribute('frontend.page.information');
$page = $pageInformation->getPageRecord();
if (empty($page['tx_sitepackage_author_name'])) {
return;
}
$author = $this->typeFactory->create('Person')
->setProperty('name', $page['tx_sitepackage_author_name'])
->setProperty('jobTitle', $page['tx_sitepackage_author_title'] ?? '')
->setProperty('description', $page['tx_sitepackage_author_bio'] ?? '');
if (!empty($page['tx_sitepackage_author_linkedin'])) {
$author->setProperty('sameAs', [$page['tx_sitepackage_author_linkedin']]);
}
$event->addType($author);
}
}
# ContentBlocks/ContentElements/faq-accordion/config.yaml
name: vendor/faq-accordion
typeName: faq_accordion
title: FAQ Accordion
description: FAQ with structured data for AI search
group: common
fields:
- identifier: faq_items
type: Collection
labelField: question
fields:
- identifier: question
type: Text
required: true
- identifier: answer
type: Textarea
enableRichtext: true
required: true
<!-- ContentBlocks/ContentElements/faq-accordion/Resources/Private/Frontend.html -->
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<section class="faq-accordion">
<schema:type.fAQPage>
<f:for each="{data.faq_items}" as="item">
<schema:type.question -as="mainEntity" name="{item.question}">
<schema:type.answer -as="acceptedAnswer">
<schema:property -as="text" value="{item.answer -> f:format.stripTags()}" />
</schema:type.answer>
</schema:type.question>
<details class="faq-item">
<summary class="faq-question">{item.question}</summary>
<div class="faq-answer">
<f:format.html>{item.answer}</f:format.html>
</div>
</details>
</f:for>
</schema:type.fAQPage>
</section>
{namespace schema=Brotkrueml\Schema\ViewHelpers}
<nav aria-label="Breadcrumb">
<schema:type.breadcrumbList>
<f:for each="{breadcrumbs}" as="crumb" iteration="iter">
<schema:type.listItem -as="itemListElement" position="{iter.cycle}">
<schema:property -as="name" value="{crumb.title}" />
<schema:property -as="item" value="{crumb.url}" />
</schema:type.listItem>
</f:for>
</schema:type.breadcrumbList>
<ol class="breadcrumb">
<f:for each="{breadcrumbs}" as="crumb" iteration="iter">
<li class="breadcrumb-item{f:if(condition: iter.isLast, then: ' active')}">
<f:if condition="{iter.isLast}">
<f:then>{crumb.title}</f:then>
<f:else>
<a href="{crumb.url}">{crumb.title}</a>
</f:else>
</f:if>
</li>
</f:for>
</ol>
</nav>
<!-- Resources/Private/Layouts/Default.html -->
<!DOCTYPE html>
<html lang="{siteLanguage.locale.languageCode}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<f:render section="HeaderAssets" optional="true" />
</head>
<body>
<header role="banner">
<f:render partial="Header" />
</header>
<nav role="navigation" aria-label="Main navigation">
<f:render partial="Navigation/Main" />
</nav>
<main role="main">
<article>
<header>
<h1>{page.title}</h1>
<f:if condition="{page.subtitle}">
<p class="lead">{page.subtitle}</p>
</f:if>
</header>
<section>
<f:render section="Content" />
</section>
</article>
</main>
<aside role="complementary">
<f:render partial="Sidebar" optional="true" />
</aside>
<footer role="contentinfo">
<f:render partial="Footer" />
</footer>
</body>
</html>
EXT:schema integrates with TYPO3's Admin Panel. Enable it to see generated JSON-LD:
# config/system/settings.php
$GLOBALS['TYPO3_CONF_VARS']['BE']['adminPanel'] = true;
After implementing structured data, validate using:
# Fetch page and extract JSON-LD
curl -s https://example.com/page | grep -o '<script type="application/ld+json">.*</script>'
This section covers AI search optimization for static sites and documentation platforms using Markdown (MD) and MDX.
Use frontmatter to define structured metadata that frameworks can transform into meta tags and structured data:
---
title: "How to Optimize Content for AI Search Engines"
description: "Complete guide to AEO and GEO strategies for ChatGPT, Perplexity, and Google AI Overviews visibility."
date: 2025-01-15
lastmod: 2025-01-15
author:
name: "Jane Doe"
title: "SEO Specialist"
linkedin: "https://linkedin.com/in/janedoe"
twitter: "https://twitter.com/janedoe"
tags: ["aeo", "geo", "ai-search", "seo"]
category: "SEO"
image: "/images/ai-search-guide.jpg"
schema:
type: "Article"
wordCount: 2500
draft: false
---
# Main Topic as H1 (Single, Contains Primary Question/Keyword)
Brief 2-3 sentence summary answering the main question directly.
This paragraph is what AI engines extract first.
## What is [Topic]?
Direct definition in 1-2 sentences. [Topic] is...
### Key Characteristics
- **Point 1:** Specific, factual information
- **Point 2:** Verifiable data with source
- **Point 3:** Actionable insight
## How Does [Topic] Work?
Clear process explanation.
1. First step with expected outcome
2. Second step with verification
3. Third step with result
## Why is [Topic] Important?
| Benefit | Impact | Evidence |
|---------|--------|----------|
| Benefit 1 | Measurable result | Source/study |
| Benefit 2 | Specific outcome | Data point |
## Frequently Asked Questions
<details>
<summary>Question 1?</summary>
Direct answer to question 1.
</details>
<details>
<summary>Question 2?</summary>
Direct answer to question 2.
</details>
// components/JsonLd.tsx
type JsonLdProps = {
data: Record<string, unknown>;
};
export function JsonLd({ data }: JsonLdProps) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(data).replace(/</g, '\\u003c'),
}}
/>
);
}
---
title: "AI Search Optimization Guide"
---
import { JsonLd } from '@/components/JsonLd';
<JsonLd data={{
"@context": "https://schema.org",
"@type": "Article",
"headline": "AI Search Optimization Guide",
"author": {
"@type": "Person",
"name": "Jane Doe"
},
"datePublished": "2025-01-15",
"dateModified": "2025-01-15"
}} />
# AI Search Optimization Guide
Content here...
npm install schema-dts astro-seo-schema
---
// src/layouts/Article.astro
import { Schema } from 'astro-seo-schema';
const { frontmatter } = Astro.props;
---
<html>
<head>
<Schema item={{
"@context": "https://schema.org",
"@type": "Article",
"headline": frontmatter.title,
"description": frontmatter.description,
"author": {
"@type": "Person",
"name": frontmatter.author.name
},
"datePublished": frontmatter.date,
"dateModified": frontmatter.lastmod
}} />
</head>
<body>
<slot />
</body>
</html>
// components/FAQ.tsx
import { JsonLd } from './JsonLd';
type FAQItem = {
question: string;
answer: string;
};
type FAQProps = {
items: FAQItem[];
};
export function FAQ({ items }: FAQProps) {
const schemaData = {
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": items.map(item => ({
"@type": "Question",
"name": item.question,
"acceptedAnswer": {
"@type": "Answer",
"text": item.answer
}
}))
};
return (
<>
<JsonLd data={schemaData} />
<section className="faq">
{items.map((item, index) => (
<details key={index}>
<summary>{item.question}</summary>
<p>{item.answer}</p>
</details>
))}
</section>
</>
);
}
import { FAQ } from '@/components/FAQ';
## Frequently Asked Questions
<FAQ items={[
{
question: "What is AEO?",
answer: "Answer Engine Optimization (AEO) is the practice of optimizing content to be cited directly in AI-generated answers."
},
{
question: "How is GEO different from SEO?",
answer: "GEO targets AI-generated search results, while traditional SEO focuses on ranking in link-based search results."
}
]} />
Enable viewing raw MDX source for transparency and AI training accessibility:
// next.config.js - Rewrite .md URLs to API
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*.md',
destination: '/api/raw-mdx?path=:path*',
},
];
},
};
// app/api/raw-mdx/route.ts
import { NextRequest, NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const filePath = searchParams.get('path');
if (!filePath) {
return NextResponse.json({ error: 'Path required' }, { status: 400 });
}
// Prevent directory traversal
const safePath = filePath.replace(/\.\./g, '');
const mdxPath = path.join(process.cwd(), 'content', `${safePath}.mdx`);
try {
const content = fs.readFileSync(mdxPath, 'utf8');
return new NextResponse(content, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
} catch {
return NextResponse.json({ error: 'Not found' }, { status: 404 });
}
}
Usage:
/docs/getting-started → Rendered page/docs/getting-started.md → Raw MDX source// app/docs/[...slug]/page.tsx
import { notFound } from 'next/navigation';
import fs from 'fs';
import path from 'path';
type Props = {
params: { slug: string[] };
searchParams: { raw?: string };
};
export default async function Page({ params, searchParams }: Props) {
const slug = params.slug.join('/');
const mdxPath = path.join(process.cwd(), 'content', `${slug}.mdx`);
// Show raw MDX if ?raw=true
if (searchParams.raw === 'true') {
try {
const rawContent = fs.readFileSync(mdxPath, 'utf8');
return (
<article>
<header>
<p className="text-sm text-gray-500">
Raw MDX source • <a href={`/docs/${slug}`}>View rendered</a>
</p>
</header>
<pre className="p-4 bg-gray-50 rounded overflow-auto">
<code>{rawContent}</code>
</pre>
</article>
);
} catch {
notFound();
}
}
// Normal MDX rendering
// ... your MDX processing
}
Usage:
/docs/getting-started → Rendered page/docs/getting-started?raw=true → Raw MDX source// lib/generateSchema.ts
type Frontmatter = {
title: string;
description: string;
date: string;
lastmod?: string;
author?: {
name: string;
title?: string;
linkedin?: string;
twitter?: string;
};
image?: string;
schema?: {
type?: 'Article' | 'HowTo' | 'FAQPage';
wordCount?: number;
};
};
export function generateSchema(frontmatter: Frontmatter, url: string) {
const schemaType = frontmatter.schema?.type || 'Article';
const baseSchema = {
"@context": "https://schema.org",
"@type": schemaType,
"headline": frontmatter.title,
"description": frontmatter.description,
"url": url,
"datePublished": frontmatter.date,
"dateModified": frontmatter.lastmod || frontmatter.date,
};
if (frontmatter.author) {
const sameAs = [
frontmatter.author.linkedin,
frontmatter.author.twitter,
].filter(Boolean);
baseSchema["author"] = {
"@type": "Person",
"name": frontmatter.author.name,
"jobTitle": frontmatter.author.title,
...(sameAs.length > 0 && { "sameAs": sameAs }),
};
}
if (frontmatter.image) {
baseSchema["image"] = frontmatter.image;
}
if (frontmatter.schema?.wordCount) {
baseSchema["wordCount"] = frontmatter.schema.wordCount;
}
return baseSchema;
}
<details>/<summary> with FAQPage schema.md or ?raw=true endpointThe llms.txt standard provides a structured, machine-readable file to help LLMs understand and navigate your website content efficiently.
Note: As of late 2025, adoption by major AI companies is still limited, but implementing llms.txt is low-effort and future-proofs your site for AI discovery.
Similar to robots.txt for crawlers, llms.txt is a Markdown file at your site root that:
# Your Company Name
> Brief one-sentence description of your site/product.
Additional context about the site, target audience, and how to use this index.
## Documentation
- [Getting Started](/docs/getting-started): Quick introduction for new users
- [API Reference](/docs/api): Complete API documentation with examples
- [Configuration Guide](/docs/configuration): Setup and configuration options
## Tutorials
- [Building Your First App](/tutorials/first-app): Step-by-step beginner guide
- [Advanced Patterns](/tutorials/advanced): In-depth exploration of features
## Optional
- [About Us](/about): Company background and team
- [Blog](/blog): Latest news and articles
- [Changelog](/changelog): Version history and updates
Key rules:
#) with site/project name>) with brief description##) for content groups[Title](URL): Description## Optional section for content LLMs can skipFor sites with extensive documentation, provide a llms-full.txt containing your entire documentation in a single Markdown file:
# Your Company Documentation
> Complete documentation for Your Company's platform.
---
## Getting Started
[Full content of getting started page...]
---
## API Reference
### Authentication
[Full API auth documentation...]
### Endpoints
[Full API endpoints documentation...]
---
## Configuration
[Full configuration documentation...]
Use cases:
TYPO3 has a dedicated extension for llms.txt generation:
# Install the extension (TYPO3 v14 — verify Packagist)
ddev composer require web-vision/ai-llms-txt
# config/sites/main/config.yaml
imports:
- resource: 'EXT:ai_llms_txt/Configuration/Routes/RouterEnhancer.yaml'
# Include extension TypoScript
@import 'EXT:ai_llms_txt/Configuration/TypoScript/setup.typoscript'
# Custom configuration
plugin.tx_aillmstxt {
settings {
# Pages to include (comma-separated UIDs or "auto")
includePages = auto
# Exclude specific pages
excludePages = 1,2,3
# Include page types
includeDoktypes = 1,4
# Maximum depth
maxDepth = 3
}
}
For full control, create a static route:
# config/sites/main/config.yaml
routes:
- route: llms.txt
type: staticText
content: |
# Your TYPO3 Site
> Enterprise content management and digital experience platform.
## Main Sections
- [Home](https://example.com/): Main landing page
- [Products](https://example.com/products): Our product catalog
- [Documentation](https://example.com/docs): Technical documentation
- [Blog](https://example.com/blog): Latest articles and news
## Optional
- [About Us](https://example.com/about): Company information
- [Contact](https://example.com/contact): Get in touch
<!-- public/llms.txt -->
# Your Next.js App
> Modern web application built with Next.js.
## Pages
- [Home](/): Main landing page
- [Documentation](/docs): Technical docs
- [Blog](/blog): Latest articles
// app/llms.txt/route.ts
import { getDocPages, getBlogPosts } from '@/lib/content';
export async function GET() {
const docs = await getDocPages();
const posts = await getBlogPosts();
const content = `# Your Site Name
> Brief description of your site.
## Documentation
${docs.map(doc => `- [${doc.title}](/docs/${doc.slug}): ${doc.description}`).join('\n')}
## Blog
${posts.slice(0, 10).map(post => `- [${post.title}](/blog/${post.slug}): ${post.excerpt}`).join('\n')}
## Optional
- [About](/about): About us
- [Contact](/contact): Get in touch
`;
return new Response(content, {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, max-age=3600, must-revalidate',
},
});
}
// app/llms-full.txt/route.ts
import { getDocPages } from '@/lib/content';
import fs from 'fs';
import path from 'path';
export async function GET() {
const docs = await getDocPages();
let fullContent = `# Complete Documentation
> Full documentation for Your Site.
`;
for (const doc of docs) {
const mdxPath = path.join(process.cwd(), 'content/docs', `${doc.slug}.mdx`);
try {
const content = fs.readFileSync(mdxPath, 'utf8');
// Remove frontmatter
const cleanContent = content.replace(/^---[\s\S]*?---\n/, '');
fullContent += `---\n\n## ${doc.title}\n\n${cleanContent}\n\n`;
} catch {
// Skip if file not found
}
}
return new Response(fullContent, {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, max-age=3600, must-revalidate',
},
});
}
npm install @waldheimdev/astro-ai-llms-txt
// astro.config.mjs
import llmsTxt from '@waldheimdev/astro-ai-llms-txt';
export default {
integrations: [
llmsTxt({
projectName: 'Your Project',
description: 'Your project description.',
site: 'https://your-domain.com',
}),
],
};
// src/pages/llms.txt.ts
import { getCollection } from 'astro:content';
import type { APIRoute } from 'astro';
export const GET: APIRoute = async () => {
const docs = await getCollection('docs');
const blog = await getCollection('blog');
const content = `# Your Astro Site
> Static site built with Astro.
## Documentation
${docs.map(doc => `- [${doc.data.title}](/docs/${doc.slug}): ${doc.data.description}`).join('\n')}
## Blog
${blog.slice(0, 10).map(post => `- [${post.data.title}](/blog/${post.slug}): ${post.data.excerpt}`).join('\n')}
`;
return new Response(content, {
headers: { 'Content-Type': 'tex
超能力技能使用指南:AI助手技能调用优先级与工作流程详解
52,100 周安装
CCBot| Common Crawl - open training datasets |
| Your content won't be in public AI training data |
| TYPO3 v14 Future | Fully supported | Requires composer.json in all extensions |
Support Modern Workflows : CI/CD pipelines, automated testing, and deployment tools expect Composer-based projects.