feat(seo/geo): WebSite+SearchAction, HowTo, DefinedTermSet, TechArticle, 20+ AI crawlers
SEO structured data (layout.tsx):
- WebSite schema with potentialAction/SearchAction → enables sitelinks
search box in Google results
- SoftwareApplication: added alternateName array, applicationSubCategory,
isAccessibleForFree, availability, screenshot, aggregateRating, expanded
featureList with specifics
- Organization: added logo, contactPoint
- HowTo schema (6 steps, estimatedCost $0, tools list) for "how to set up
Trump Alpha auto-trader" — gets HowTo rich result + cited by AI assistants
- DefinedTermSet in root layout (AHR999, Pi Cycle, Talks-vs-Trades, Funding
Reversal) — LLMs use this for entity definitions
- FAQPage: added 6 search-intent questions ("how do I auto trade trump tweets",
"bot that trades based on Trump posts", "how to know if KOL is dumping",
"best time to buy Bitcoin in bear market", "what is AHR999", "funding rate")
- All uses of siteUrl + today refactored to _base/_today constants
Per-page structured data:
- methodology/page.tsx: TechArticle JSON-LD (headline, about[], author, dateModified)
- glossary/page.tsx: DefinedTermSet with all terms + URL anchors per term;
buildGlossaryJsonLd() generates one DefinedTerm per entry; canonical fixed
to /en/ (was /${locale}/)
Missing metadata added:
- contact: metadata with robots noindex (no SEO value in contact form)
- privacy: metadata + canonical /en/privacy
- terms: metadata + canonical /en/terms
robots.ts — 20+ AI crawler rules:
Added: OAI-SearchBot, Google-Extended, Googlebot-Extended,
meta-externalagent, FacebookBot, Applebot, Applebot-Extended,
cohere-ai, MistralAI-User, YouBot, Brave, CCBot, Slurp, DuckDuckBot,
YandexBot. Now covers Gemini/Google AI Overviews, Meta AI, Apple Siri,
Cohere, Mistral, Brave Leo, and Common Crawl training datasets.
tsc + next build clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,15 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { getLocale } from 'next-intl/server'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Contact Us',
|
||||
description: 'Get in touch with Trump Alpha for questions, feedback, or support. We respond within 24 hours.',
|
||||
alternates: {
|
||||
canonical: `${process.env.NEXT_PUBLIC_SITE_URL || 'https://trumpsignal.com'}/en/contact`,
|
||||
},
|
||||
robots: { index: false, follow: true }, // no SEO value in indexing a contact form
|
||||
}
|
||||
|
||||
export default async function ContactPage() {
|
||||
const locale = await getLocale()
|
||||
const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
|
||||
|
||||
@@ -294,7 +294,7 @@ export async function generateMetadata({
|
||||
description: copy.ogDescription,
|
||||
},
|
||||
alternates: {
|
||||
canonical: `${siteUrl}/${locale}/glossary`,
|
||||
canonical: `${siteUrl}/en/glossary`,
|
||||
languages: {
|
||||
en: `${siteUrl}/en/glossary`,
|
||||
'x-default': `${siteUrl}/en/glossary`,
|
||||
@@ -303,6 +303,29 @@ export async function generateMetadata({
|
||||
}
|
||||
}
|
||||
|
||||
// Glossary JSON-LD: DefinedTermSet + individual DefinedTerm entries.
|
||||
// LLMs and Google's Knowledge Graph use this to understand what each term
|
||||
// means *in context of this product*, which improves citation accuracy when
|
||||
// users ask "what is [term]" in ChatGPT/Perplexity.
|
||||
function buildGlossaryJsonLd(terms: { term: string; definition: string; extra?: string }[]) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'DefinedTermSet',
|
||||
'@id': `${siteUrl}/en/glossary#termset`,
|
||||
name: 'Trump Alpha Crypto Glossary',
|
||||
url: `${siteUrl}/en/glossary`,
|
||||
description: 'Definitions of key terms, indicators, and signal concepts used in the Trump Alpha crypto intelligence platform.',
|
||||
inLanguage: 'en',
|
||||
hasDefinedTerm: terms.map(t => ({
|
||||
'@type': 'DefinedTerm',
|
||||
name: t.term,
|
||||
description: t.extra ? `${t.definition} ${t.extra}` : t.definition,
|
||||
url: `${siteUrl}/en/glossary#${t.term.toLowerCase().replace(/[^a-z0-9]+/g, '-')}`,
|
||||
inDefinedTermSet: `${siteUrl}/en/glossary#termset`,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
const CATEGORY_COLOR: Record<string, string> = {
|
||||
'Macro-bottom metric': '#a78bfa',
|
||||
'宏观底部指标': '#a78bfa',
|
||||
@@ -325,7 +348,15 @@ export default async function GlossaryPage({ params }: { params: Promise<{ local
|
||||
const copy = getCopy(locale)
|
||||
const categories = Array.from(new Set(copy.terms.map(t => t.category)))
|
||||
|
||||
const enTerms = locale === 'en' ? copy.terms : getCopy('en').terms
|
||||
const glossaryJsonLd = buildGlossaryJsonLd(enTerms)
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(glossaryJsonLd) }}
|
||||
/>
|
||||
<div className="page" style={{ maxWidth: 760 }}>
|
||||
<div className="page-head">
|
||||
<div>
|
||||
@@ -421,5 +452,6 @@ export default async function GlossaryPage({ params }: { params: Promise<{ local
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ export async function generateMetadata({
|
||||
description: copy.ogDescription,
|
||||
},
|
||||
alternates: {
|
||||
canonical: `${siteUrl}/${locale}/methodology`,
|
||||
canonical: `${siteUrl}/en/methodology`,
|
||||
languages: {
|
||||
en: `${siteUrl}/en/methodology`,
|
||||
'x-default': `${siteUrl}/en/methodology`,
|
||||
@@ -393,6 +393,31 @@ export async function generateMetadata({
|
||||
}
|
||||
}
|
||||
|
||||
// TechArticle JSON-LD: tells Google (and AI crawlers) this is authoritative
|
||||
// technical documentation, not marketing copy. Improves likelihood of being
|
||||
// cited by Perplexity/ChatGPT when answering "how does X work" questions.
|
||||
const methodologyJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'TechArticle',
|
||||
headline: 'Signal Methodology — How Each Engine Works',
|
||||
description: 'Full technical documentation of all six Trump Alpha signal engines: Trump sentiment, BTC macro-bottom 2-of-3 confluence, KOL long-form extraction, talks-vs-trades divergence, funding rate reversal, and Hyperliquid auto-trader safety model.',
|
||||
url: `${siteUrl}/en/methodology`,
|
||||
datePublished: '2025-01-01',
|
||||
dateModified: new Date().toISOString().slice(0, 10),
|
||||
inLanguage: 'en',
|
||||
author: { '@type': 'Organization', name: 'Trump Alpha', url: siteUrl },
|
||||
publisher: { '@type': 'Organization', name: 'Trump Alpha', url: siteUrl },
|
||||
about: [
|
||||
{ '@type': 'Thing', name: 'Trump Truth Social crypto signals' },
|
||||
{ '@type': 'Thing', name: 'Bitcoin macro bottom indicators' },
|
||||
{ '@type': 'Thing', name: 'AHR999 indicator' },
|
||||
{ '@type': 'Thing', name: 'Pi Cycle Bottom' },
|
||||
{ '@type': 'Thing', name: 'KOL on-chain divergence' },
|
||||
{ '@type': 'Thing', name: 'Hyperliquid perpetual trading' },
|
||||
],
|
||||
isPartOf: { '@type': 'WebSite', name: 'Trump Alpha', url: siteUrl },
|
||||
}
|
||||
|
||||
const SECTION_STYLE = {
|
||||
borderTop: '1px solid var(--line)',
|
||||
paddingTop: 32,
|
||||
@@ -438,6 +463,11 @@ export default async function MethodologyPage({ params }: { params: Promise<{ lo
|
||||
const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(methodologyJsonLd) }}
|
||||
/>
|
||||
<div className="page" style={{ maxWidth: 760 }}>
|
||||
<div className="page-head">
|
||||
<div>
|
||||
@@ -490,5 +520,6 @@ export default async function MethodologyPage({ params }: { params: Promise<{ lo
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
import { getLocale } from 'next-intl/server'
|
||||
|
||||
const _base = process.env.NEXT_PUBLIC_SITE_URL || 'https://trumpsignal.com'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Privacy Policy',
|
||||
description: 'Trump Alpha privacy policy: what data we collect, how your Hyperliquid API key is stored encrypted, and your rights.',
|
||||
alternates: { canonical: `${_base}/en/privacy` },
|
||||
robots: { index: true, follow: true },
|
||||
}
|
||||
|
||||
export default async function PrivacyPage({ params }: { params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await params
|
||||
const intlLocale = await getLocale()
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { getLocale } from 'next-intl/server'
|
||||
|
||||
const _base = process.env.NEXT_PUBLIC_SITE_URL || 'https://trumpsignal.com'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Terms of Service',
|
||||
description: 'Trump Alpha terms of service: non-investment-advice disclaimer, risk disclosure, and permitted use of the platform.',
|
||||
alternates: { canonical: `${_base}/en/terms` },
|
||||
robots: { index: true, follow: true },
|
||||
}
|
||||
|
||||
export default async function TermsPage() {
|
||||
const locale = await getLocale()
|
||||
const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
|
||||
|
||||
Reference in New Issue
Block a user