Resource icon

LLMO SEO Indexing AI Addon 2.1.4 (my last try)

No permission to download
🧩 LLMO SEO ADD-ON (XenForo 2.3, PHP 8.4)

Overview:
LLMO SEO automatically injects structured JSON-LD metadata (Schema.org + custom "llmo" context) into XenForo threads, resources, forums, and user profiles. It improves SEO and makes forum content machine-readable for search engines and AI models. Compatible with XenForo 2.3.7+ and PHP 8.4.

-------------------------------------------------
📦 INSTALLATION STEPS

1. Download:
Vendor_LlmoSeo_1.0.1.zip

2. Upload:
Option A: Unzip into src/addons/Vendor/LlmoSeo/
Option B: Upload the zip via XenForo Admin → Add-ons → Install/Upgrade from archive.

3. Install:
Admin Control Panel → Add-ons → Find “LLMO SEO” → Click “Install”.

-------------------------------------------------
⚙️ CONFIGURATION

Go to: Admin → Options → LLMO SEO

Options available:
  • llmoseo_enable (bool): enable or disable JSON-LD injection
  • llmoseo_debug (bool): add debug header “X-LLMO-SEO”
  • llmoseo_strip_pii (bool): remove emails, phones, IPs from data
  • llmoseo_cache_ttl (int): cache lifetime in seconds (default 3600)
  • llmoseo_route_whitelist (textarea): allowed routes (ex: threads/, forums/, resources/, members/)

-------------------------------------------------
🧠 HOW IT WORKS

For each supported page:
1. Detects the current context (thread/resource/forum/user)
2. Extracts entities (title, author, date, etc.)
3. Determines intent (howTo, troubleshooting, comparison, reference)
4. Builds Schema.org JSON-LD (DiscussionForumPosting, SoftwareApplication, CollectionPage, Person)
5. Injects it in the <head> of the page as:

<script id="llmo-seo" type="application/ld+json">…JSON content…</script>

-------------------------------------------------
🔍 VALIDATION

Option 1: Using CLI command
php cmd.php llmo:validate https://yourforum.com/threads/example-thread/

Validates:
  • JSON structure
  • Presence of @context and @type
  • Size ≤ 50 KB

Option 2: Google Rich Results

-------------------------------------------------
🧰 DEBUGGING

If llmoseo_debug = true, headers like:
X-LLMO-SEO: hit=1;type=thread;intent=howTo;size=12.4KB
will appear in browser DevTools → Network → Headers.

-------------------------------------------------
🔒 SECURITY

  • Automatically redacts PII (emails, phones, IPs) when llmoseo_strip_pii is enabled.
  • JSON-LD is non-executable (application/ld+json).
  • CSP recommendation: Content-Security-Policy: script-src 'self';
  • Partial template only renders inside <head> when JSON exists.

-------------------------------------------------
🚀 RECOMMENDED ROUTES

Whitelist examples:
threads/*
forums/*
resources/*
members/*

-------------------------------------------------
🧬 EXAMPLE JSON-LD OUTPUT

{
"@context": ["https://schema.org", "llmo": "https://llmo.vendor.dev/context/v1"],
"@type": "DiscussionForumPosting",
"headline": "How to install PHP 8.4 on Ubuntu",
"author": { "@type": "Person", "name": "Alice" },
"datePublished": "2025-01-12T10:15:00+00:00",
"url": "https://forum.example.com/threads/123/",
"inLanguage": "en",
"mainEntity": {
"@type": "QAPage",
"acceptedAnswer": { "@type": "Answer", "text": "See the accepted solution in the thread." }
},
"llmo:reasoningHints": {
"intent": "howTo",
"entities": { "id": 123, "title": "How to install PHP 8.4", "author": "Alice" }
}
}

-------------------------------------------------
✅ PHP 8.4 COMPATIBILITY

  • declare(strict_types=1); used everywhere
  • No dynamic properties
  • #[\Override] annotations on overridden methods
  • Typed parameters and returns
  • Dates formatted with DATE_ATOM (ISO 8601)

-------------------------------------------------
📈 ROADMAP

  • Local entity extraction (regex or NLP)
  • AI-ready metadata snippets with confidence scores
  • Multilingual entity alignment using “sameAs”

-------------------------------------------------
🔧 QUICK TEST

After installation, open any thread/resource page → View Source.
You should see near the end of <head>:
<script id="llmo-seo" type="application/ld+json">…</script>
 
# LLMO SEO — VALIDATION SCRIPTS (PowerShell & Linux)

# Test domain used below: https://forum.example.com/threads/123/
# Copy the two scripts into files as named, make them executable (Linux),
# then run with your forum URL or rely on the default test URL.

==================================================
# FILE: Validate-Llmo.ps1 (PowerShell, Windows/macOS/Linux)
# USAGE NOTE:
# 1) Save as: Validate-Llmo.ps1
# 2) Run:
# pwsh ./Validate-Llmo.ps1 -Url "https://yourforum.tld/threads/123/"
# or (Windows PowerShell):
# powershell -ExecutionPolicy Bypass -File .\Validate-Llmo.ps1 -Url "https://yourforum.tld/threads/123/"
# 3) Default (no param) uses the test domain: https://forum.example.com/threads/123/
# What it does:
# - Fetches the page, extracts <script id="llmo-seo">…</script>,
# - HTML-decodes its content, parses JSON, checks @context/@type and size ≤ 50 KB.
# Exit codes: 0 = valid, 1 = invalid/error.

param(
[Parameter(Position=0)]
[string]$Url = "https://forum.example.com/threads/123/"
)

try {
$resp = Invoke-WebRequest -Uri $Url -TimeoutSec 15
} catch {
Write-Error "HTTP request failed: $($_.Exception.Message)"; exit 1
}

$html = $resp.Content
$regex = '<script[^>]+id=["'']llmo-seo["''][^>]>(.?)</script>'
$opts = [System.Text.RegularExpressions.RegexOptions]::Singleline -bor `
[System.Text.RegularExpressions.RegexOptions]::IgnoreCase
$m = [regex]::Match($html, $regex, $opts)

if (-not $m.Success) { Write-Host "ERROR: No LLMO JSON-LD found."; exit 1 }

$raw = [System.Net.WebUtility]::HtmlDecode($m.Groups[1].Value)

try {
$json = $raw | ConvertFrom-Json -Depth 64
} catch {
Write-Host "ERROR: Invalid JSON: $($_.Exception.Message)"; exit 1
}

$bytes = [System.Text.Encoding]::UTF8.GetBytes($raw)
if ($bytes.Length -gt 51200) {
Write-Host "ERROR: JSON-LD exceeds 50KB."; exit 1
}

$hasContext = $json.PSObject.Properties.Name -contains "@context"
$hasType = $json.PSObject.Properties.Name -contains "@type"
if (-not ($hasContext -and $hasType)) {
Write-Host "ERROR: Missing @context or @type."; exit 1
}

$type = $json.'@type'
Write-Host ("OK: LLMO JSON-LD valid. Size={0} bytes; type={1}" -f $bytes.Length, $type)
exit 0


==================================================
# FILE: validate-llmo.sh (Linux/macOS with bash + Python 3)
# USAGE NOTE:
# 1) Save as: validate-llmo.sh
# 2) Make executable: chmod +x validate-llmo.sh
# 3) Run:
# ./validate-llmo.sh "https://yourforum.tld/threads/123/"
# Or rely on default (test domain) if no URL is passed:
# ./validate-llmo.sh
# Requirements: bash + python3 (standard library only; no extra packages).
# What it does:
# - Fetches the page, extracts <script id="llmo-seo">…</script>,
# - HTML-decodes its content, parses JSON, checks @context/@type and size ≤ 50 KB.
# Exit codes: 0 = valid, 1 = invalid/error.

#!/usr/bin/env bash
set -euo pipefail
URL="${1:-https://forum.example.com/threads/123/}"

python3 - "$URL" <<'PYCODE'
import sys, re, html, json, urllib.request

def main(url: str) -> int:
try:
with urllib.request.urlopen(url, timeout=15) as r:
html_text = r.read().decode('utf-8', 'replace')
except Exception as e:
print(f"ERROR: HTTP request failed: {e}", file=sys.stderr)
return 1

m = re.search(r'<script[^>]+id=["\']llmo-seo["\'][^>]>(.?)</script>', html_text, re.I | re.S)
if not m:
print("ERROR: No LLMO JSON-LD found.", file=sys.stderr)
return 1

raw = html.unescape(m.group(1))

try:
data = json.loads(raw)
except Exception as e:
print(f"ERROR: Invalid JSON: {e}", file=sys.stderr)
return 1

size = len(raw.encode('utf-8'))
if size > 50 * 1024:
print("ERROR: JSON-LD exceeds 50KB.", file=sys.stderr)
return 1

if "@context" not in data or "@type" not in data:
print("ERROR: Missing @context or @type.", file=sys.stderr)
return 1

print(f"OK: LLMO JSON-LD valid. Size={size} bytes; type={data.get('@type')}")
return 0

if name == "main":
sys.exit(main(sys.argv[1]))
PYCODE
 
Roiarthur updated LLMO SEO Indexing AI Addon with a new update entry:

Update LLMOSeo to 2.1.0

LLMO SEO — v2.1.0 Corrective Notes (English)

Scope
This release addresses packaging and metadata issues reported by XenForo’s Resource Manager: missing option groups, options, and routes, plus icon duplication and hashes placement.

Fixes & Additions
1) Option Group (NEW)
- Added _data/option_groups/llmoseo.json
- Group ID: llmoseo
- Title: “LLMO SEO” (order 1000)
- Purpose: Properly hosts all add-on options in Admin → Options.

2) Options (NEW, 5 items)
- Added...

Read the rest of this update entry...
 
I forgot to integrate the hashes.json and the icon i am creating an update to test
I don’t really know how you are creating the ZIP files but there clearly seem to be issues.

Basically all you have to do is run

cmd.php xf-addon:build-release Vendor/AddOnId

via cli on your dev system, this will create a proper ZIP within _releases folder of the Add-on.

The 2.1.0 ZIP is still not a fully valid XenForo Add-on packsge.
 
Last edited:
@Kirby is right @Roiarthur . Your folder structure is wrong. When you unzip the file, you want it to look something like: \Vendor_LlmoSeo_1.0.1\upload\src\addons\Vendor\LlmoSeo\............ You really don't need Vendor in it.

Also, be sure to include all files in each zip you do for releases. Your folder/file structure is all over the place. With missing this file and that file.
 
Unfortunately this is again not a valid XenForo Add- on ZIP and seems to be missing some of the files mentioned in https://xenforo.com/community/threads/llmo-seo-indexing-ai-addon.233659/post-1761662.

A valid Add-on ZIP has only XML files without subdirectories in _data, not JSON files.

To create it you just have to call
cmd.php xf-addon:build-release Vendor/AddOnId
from the shell on your dev system, this will create a valid ZIP package in _releases folder of the Add-on.
 
Back
Top Bottom