Roiarthur
Active member
XenForo is a beast, but its default SEO is a bit "generic". It throws "DiscussionForumPosting" at Google while you are writing technical masterpieces. If you just paste your script blindly into the footer, Google will laugh. We are going to use the XF template engine to inject this dynamically into the <head>, and only on your tutorials. No paid plugins, just clean code.
XenForo Admins who aren't afraid to touch the "Appearance" button and want quality Rich Snippets.
• AdminCP Access (admin.php)
• The Forum ID (Node ID) where you post your tutorials (e.g., the "Windows" forum is ID 12)
• "Development Mode" enabled (optional but recommended to avoid breaking prod)
Step #1 > Easy > Locate the thread_view template
Step #2 > Intermediate > Conditional Code Injection
Explanation : Open the template and position yourself at the very top, after the macros.
Code:
AdminCP > Appearance > Templates > thread_view
Explanation : Copy this block to the very top of the thread_view template. Replace '10' with your tutorial forum ID.
Code:
<xf:if is="$thread.node_id == 10">
<xf:head option="ld_json_techarticle">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "{$thread.title|escape('json')}",
"image": "{$xf.options.boardUrl}/styles/default/xenforo/xenforo-logo.png",
"author": {
"@type": "Person",
"name": "{$thread.User.username|escape('json')}"
},
"publisher": {
"@type": "Organization",
"name": "{$xf.options.boardTitle|escape('json')}",
"logo": {
"@type": "ImageObject",
"url": "{$xf.options.boardUrl}/styles/default/xenforo/xenforo-logo.png"
}
},
"datePublished": "{{ date($thread.post_date, 'c') }}",
"dateModified": "{{ date($thread.last_post_date, 'c') }}",
"description": "{$thread.FirstPost.message|snippet(160)|escape('json')}"
}
</script>
</xf:head>
</xf:if>
If error : White page or Template syntax error.
Fix : Check that you have closed the <xf:if> tag. Check that you haven't forgotten a comma in the JSON.
Code:
Validate your JSON on https://validator.schema.org/ after modification
On XenForo 1.x, it was a jungle. On 2.3, the use of <xf:head> is clean: it automatically moves the script to the final HTML header, even if you write it in the middle of the body in the template. It's magic.
For the image, if you use an addon that allows "Featured Images" for threads, you can replace the logo URL with the addon variable (often {$thread.CoverImage}). Otherwise, Google will settle for the site logo, which is better than nothing.
Do not put this code in PAGE_CONTAINER without a strict condition. Otherwise, your "Privacy Policy" or "Member List" pages will declare themselves as "TechArticle", and Google will penalize you for misleading data.
If you have multiple tutorial forums (e.g., Windows, Linux, Mac), use an array in the condition: <xf:if is="in_array($thread.node_id, [10, 12, 15])">. Saves you from duplicating code.
• XenForo Template Documentation
• Schema.org Validation Tool
• Google TechArticle Docs
• Search with Google
Never copy a static JSON-LD script into a dynamic CMS. Use the {$thread} variables and the <xf:head> tag in the thread_view template. It's the only "clean" way to tell Google: "Hey, look, this is a real technical tutorial, not just forum chatter". Now, save and clear the cache.