Migrate Article Schema to FinancialProduct on DeFi Protocol Pages
The single highest-ROI schema fix in DeFi. About 88% of protocol pages run Article schema by default. This is how to migrate cleanly without breaking validation.
Why this matters
- →Across 200+ TG3 client audits, sites with proper FinancialProduct schema get cited by AI engines 3-4x more than sites with Article schema.
- →Article schema on a protocol page makes Google's rich result systems treat your page as a blog post. No FinancialProduct-specific rich features eligible.
- →Most DeFi sites use Yoast or RankMath which emit Article schema by default. Override is required.
- →Single migration typically lifts organic traffic 30-50% within 60 days based on TG3 client data.
Before state (what bad looks like)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Aave - Decentralized Lending Protocol",
"description": "Aave is a DeFi lending protocol...",
"image": "https://example.com/aave-hero.png",
"datePublished": "2024-01-15"
}
</script>
Step-by-step
Step 1: Identify all protocol pages on your site
Run a site crawl with Screaming Frog (free up to 500 URLs) or use Google Search Console's Pages report. Filter for URLs that describe a single DeFi protocol: typically /protocols/{name}/, /defi/{name}/, or your homepage if you ARE the protocol. Document the list. You'll need it for batch migration.
Step 2: Audit current schema on those pages
Open Schema.org Validator (validator.schema.org) and paste in each protocol page URL. Note which schema types are emitted. Most likely findings: Article from Yoast/RankMath, plus BreadcrumbList from your CMS, possibly Organization. The Article entry is what you're replacing.
Step 3: Override your CMS's default Article schema
If you're on WordPress with Yoast or RankMath, both have hooks to override schema. Add this to your theme's functions.php to remove Article schema on protocol pages:
<?php
add_filter('rank_math/json_ld', function($data, $jsonld) {
if (is_singular('protocol')) { // adjust to your post type
unset($data['richSnippet']);
}
return $data;
}, 10, 2);
// For Yoast equivalent:
add_filter('wpseo_schema_graph_pieces', function($pieces, $context) {
if (is_singular('protocol')) {
return array_filter($pieces, function($piece) {
return !($piece instanceof \Yoast\WP\SEO\Generators\Schema\Article);
});
}
return $pieces;
}, 11, 2);
Step 4: Inject FinancialProduct schema via custom JSON-LD
Add a custom JSON-LD block to your protocol page template. For WordPress, use a custom field or ACF (Advanced Custom Fields) to store per-protocol data, then render in the head. The graph approach lets you stack FinancialProduct + BreadcrumbList + FAQPage cleanly. Use the "After state" example above as your template.
Step 5: Add FAQPage schema with 5+ questions
On the same protocol page, add FAQPage schema with the explicit trust and how-it-works questions. AI engines extract these heavily for retrieval. Stack with FinancialProduct via shared @graph wrapper.
{
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Is Aave safe to use?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Aave has been audited 12+ times..."
}
}
]
}
Step 6: Validate against three validators
Run the migrated page through Schema.org Validator (catches syntax), Google Rich Results Test (catches eligibility), and Bing Markup Validator (stricter parsing, important because ChatGPT uses Bing for retrieval). Pass all three before deploying. Schema.org first because syntax errors block everything else.
Step 7: Deploy and monitor in Search Console
Push to production. Submit the updated URL in GSC URL Inspection tool to request re-indexation. Monitor the "Enhancements" tab in Search Console over the next 7-14 days. New rich result types should appear (FAQ, Sitelinks). Track organic traffic on the page over 30/60/90 days for ranking lift.
FREE WEB3 AUDIT
See where this playbook applies to your site.
Run a free Crawlux audit before you start the playbook. It tells you which fixes are most urgent.
Free first audit · No signup · 60 seconds · Full PDF report
After state (what good looks like)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "FinancialProduct",
"@id": "https://example.com/aave/#product",
"name": "Aave",
"description": "Aave is a DeFi lending protocol with $11.2B TVL across 11 chains.",
"url": "https://example.com/aave/",
"provider": {
"@type": "Organization",
"name": "Aave Companies",
"url": "https://aave.com"
},
"termsOfService": "https://example.com/aave/terms/",
"feeStructure": {
"@type": "PriceSpecification",
"description": "Variable APY based on utilization"
},
"audience": {
"@type": "Audience",
"audienceType": "DeFi users"
},
"additionalProperty": [
{"@type": "PropertyValue", "propertyID": "totalValueLocked", "value": "11200000000"},
{"@type": "PropertyValue", "propertyID": "auditedContract", "value": "0x..."}
]
},
{
"@type": "BreadcrumbList",
"itemListElement": [
{"@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/"},
{"@type": "ListItem", "position": 2, "name": "Protocols", "item": "https://example.com/protocols/"},
{"@type": "ListItem", "position": 3, "name": "Aave"}
]
}
]
}
</script>
How to validate the fix
- ✓Schema.org Validator returns 0 errors and 0 warnings on the FinancialProduct entity.
- ✓Google Rich Results Test reports the page as eligible for FAQ rich results (FinancialProduct itself isn't in Google's primary rich result types yet but FAQ stacked on top is).
- ✓Bing Markup Validator returns 0 errors.
- ✓GSC URL Inspection shows the new schema in the rendered HTML.
- ✓After 7-14 days, GSC Enhancements tab shows FAQ rich results activity.
Common pitfalls
Pitfall
Forgetting to remove the old Article schema
If you add FinancialProduct without removing Article, both emit. Google deduplicates poorly when conflicting schema types describe the same entity. Always strip the old one first.
Pitfall
Missing required properties
FinancialProduct requires name and description at minimum. Validators will flag missing required fields. Fill them all.
Pitfall
Using string for feeStructure
feeStructure should be PriceSpecification or QuantitativeValue, not a plain string. Plain strings fail validation.
Pitfall
Skipping the @graph wrapper
Using top-level @type when stacking multiple entities creates messy schema. Always use @graph: [...] when you have FinancialProduct + BreadcrumbList + FAQPage on the same page.
Pitfall
Not testing on mobile-rendered HTML
If your site uses CSR, run validation on the actual rendered DOM via Puppeteer, not the initial HTML. Schema in script tags should still work but test it.
If something breaks: rollback
If schema causes issues post-deploy: revert the functions.php override to restore Article schema, remove the custom FinancialProduct injection. Old schema is back within minutes. No data loss because schema is metadata only.
Run a free Crawlux audit on this fix
Crawlux validates the schema, technical and AEO fixes from this playbook automatically. Free tier on one domain.
Run free audit →FAQ
Why FinancialProduct and not Service or Product?
FinancialProduct extends Service in the Schema.org hierarchy and has crypto-relevant properties (feeStructure, termsOfService, audited contract identifiers). Service is too generic. Product is for physical goods or software. FinancialProduct is purpose-built for financial offerings including DeFi protocols.
Will this hurt my existing rankings?
No. Schema migrations are metadata changes. They lift rankings when done correctly. The risk is broken syntax breaking schema parsing entirely, which is why three-validator testing is mandatory before deploy.
How long until I see ranking impact?
Schema fixes typically show in 2-4 weeks for crawl/recrawl, 30-60 days for full ranking impact. AEO citations can lift faster (2-4 weeks) because AI engines re-crawl frequently.
Can I do this without touching code?
Partially. Schema App and similar tools let you inject schema via tag manager. Works but limited. Full migration requires either CMS hooks (Yoast/RankMath filters) or custom template work. Budget 30-45 minutes if you have dev access; 2-4 hours if you don't.
What if my CMS doesn't support custom JSON-LD injection?
Use Google Tag Manager or a custom HTML widget in your CMS to inject the JSON-LD. Less clean than template-level injection but works. Only downside: dependent on JS execution which means SEO crawlers may miss it occasionally.
Related playbooks
Pillar guides
Audit modules
RUN YOUR FIRST AUDIT
Run the playbook against a real audit.
Get a free Crawlux audit report and use it as the baseline for the work in this playbook.
Free first audit · No signup · 60 seconds · Full PDF report
