From 04840b2648415f65d803dc6d867101c344ee482b Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Thu, 30 Jul 2026 04:13:04 +0000
Subject: [PATCH] feat: Add new GEO factors to AI Readiness Audit
- Implemented four new checks based on Generative Engine Optimization best practices:
- HTML Language Attribute
- Title Tag
- Image Alt Text
- RSS/Atom Feed
- Updated `HTMLRewriter` parsing logic to efficiently detect the new factors in a single pass.
- Updated `contentMetadata` with prompts, statuses, specifications, and tooltips for these new elements.
- Factored new elements into the final total score (each awards +5).
- All vitest test suites passed successfully.
Co-authored-by: SecH0us3 <5781038+SecH0us3@users.noreply.github.com>
---
ai-valid/src/index.js | 73 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/ai-valid/src/index.js b/ai-valid/src/index.js
index ee89c61..fe66bdd 100644
--- a/ai-valid/src/index.js
+++ b/ai-valid/src/index.js
@@ -619,6 +619,10 @@ async function performAudit(baseUrl, requestOrigin, env, ctx) {
let hasWebMCP = false;
let hasARIA = false;
let hasMetaDesc = false;
+ let hasHtmlLang = false;
+ let hasTitleTag = false;
+ let hasImgAlt = false;
+ let hasRssFeed = false;
let currentScriptText = '';
try {
@@ -681,6 +685,35 @@ async function performAudit(baseUrl, requestOrigin, env, ctx) {
let lowerHtmlText = '';
const transformed = new HTMLRewriter()
+ .on('html', {
+ element(el) {
+ if (el.getAttribute('lang')) {
+ hasHtmlLang = true;
+ }
+ }
+ })
+ .on('title', {
+ element() {
+ hasTitleTag = true;
+ }
+ })
+ .on('img', {
+ element(el) {
+ const alt = el.getAttribute('alt');
+ if (alt && alt.trim() !== '') {
+ hasImgAlt = true;
+ }
+ }
+ })
+ .on('link', {
+ element(el) {
+ const rel = (el.getAttribute('rel') || '').toLowerCase();
+ const type = (el.getAttribute('type') || '').toLowerCase();
+ if (rel === 'alternate' && (type === 'application/rss+xml' || type === 'application/atom+xml')) {
+ hasRssFeed = true;
+ }
+ }
+ })
.on('meta', {
element(el) {
const name = (el.getAttribute('name') || '').toLowerCase();
@@ -856,6 +889,10 @@ async function performAudit(baseUrl, requestOrigin, env, ctx) {
if (hasWebMCP) totalScore += 10;
if (hasARIA) totalScore += 5;
if (hasMetaDesc) totalScore += 5;
+ if (hasHtmlLang) totalScore += 5;
+ if (hasTitleTag) totalScore += 5;
+ if (hasImgAlt) totalScore += 5;
+ if (hasRssFeed) totalScore += 5;
// Process JSON-LD blocks extracted by HTMLRewriter
for (const block of jsonLdChunks) {
@@ -1389,6 +1426,42 @@ Examples of specific types:
spec: "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name",
tooltip: `What it is: The <meta name="description"> or Open Graph (og:) tags in the HTML head.
Why it's critical for GEO: Answer Engines and AI crawlers often extract these tags to quickly summarize a page when detailed schema is unavailable.
Impact of missing it: AI models may generate sub-optimal or irrelevant summaries of your page content in search results.
Implementation Example: <meta name="description" content="A comprehensive guide to...">`,
code: hasMetaDesc ? 'Found' : 'Missing'
+ },
+ {
+ name: "HTML Language Attribute",
+ prompt: `Add a 'lang' attribute to the tag of my website to declare the primary language of the document.`,
+ status: hasHtmlLang ? 'ok' : 'warn',
+ message: hasHtmlLang ? "HTML language attribute found" : "Missing HTML language attribute",
+ spec: "https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang",
+ tooltip: `What it is: The lang attribute on the root <html> element.
Why it's critical for GEO: It explicitly tells AI and answer engines the language of the content, ensuring correct indexing and appropriate responses for international users.
Impact of missing it: LLMs might misidentify the language, reducing the likelihood of your content being cited in localized queries.
Implementation Example: <html lang="en">`,
+ code: hasHtmlLang ? 'Found' : 'Missing'
+ },
+ {
+ name: "Title Tag",
+ prompt: `Add a descriptive
<title> element within the <head>.<title>My Awesome Website</title>`,
+ code: hasTitleTag ? 'Found' : 'Missing'
+ },
+ {
+ name: "Image Alt Text",
+ prompt: `Ensure all meaningful images on my website have descriptive 'alt' attributes.`,
+ status: hasImgAlt ? 'ok' : 'warn',
+ message: hasImgAlt ? "Image alt text found" : "Missing image alt text",
+ spec: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt",
+ tooltip: `What it is: The alt attribute on <img> tags that describes the image content.<img src="chart.png" alt="Sales growth chart for 2024">`,
+ code: hasImgAlt ? 'Found' : 'Missing'
+ },
+ {
+ name: "RSS/Atom Feed",
+ prompt: `Provide an RSS or Atom feed for my website's content and link to it in the .`,
+ status: hasRssFeed ? 'ok' : 'warn',
+ message: hasRssFeed ? "RSS/Atom feed found" : "Missing RSS/Atom feed",
+ spec: "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link",
+ tooltip: `What it is: A link element pointing to an RSS or Atom feed.<link rel="alternate" type="application/rss+xml" href="/feed.xml">`,
+ code: hasRssFeed ? 'Found' : 'Missing'
}
].sort((a, b) => {
const weights = {