Most dApps default to CSR because blockchain interactions happen in the browser, but Googlebot may not wait for all the JavaScript to finish executing.
When that happens, the crawler indexes an empty shell: a page with a loading spinner and almost no text. I see this constantly when I audit dApps. The team is convinced the page is “full of content,” but view-source shows a near-empty <div id="root"> and nothing for Google to read.
The fix is to stop forcing the crawler to do work it will not reliably finish. There are three routes, depending on your stack:
- Server-side rendering (SSR): the server builds the HTML on each request and sends a complete page. Best for content that changes often. Frameworks like Next.js and Nuxt handle this well.
- Static site generation (SSG): pages are pre-built at deploy time and served as flat HTML. Best for content that rarely changes, like docs, blogs, and landing pages. It is the fastest option and the easiest for crawlers.
- Dynamic rendering: you detect bots and serve them a pre-rendered HTML version while users get the normal app. Google has called this a workaround rather than a long-term answer, so treat it as a bridge, not a destination.
Here is the rule I give every team: the wallet and the on-chain interactivity can stay client-side. The words, headings, links, and metadata that you want ranked must exist in the initial HTML response. Test it the lazy way: open the page, right-click, “View page source,” and search for a sentence from your copy. If it is not there, Google probably cannot see it either. I go deeper on diagnosing and fixing this in my guide to JavaScript SEO for Web3 dApps.
| Rendering method | Crawler sees content | Best for |
|---|---|---|
| Client-side (CSR) | Unreliable | App dashboards behind a wallet |
| Server-side (SSR) | Yes | Frequently updated content |
| Static (SSG) | Yes, fastest | Docs, blogs, marketing pages |
| Dynamic rendering | Yes, bridge only | Legacy apps you cannot refactor |
How to Render Wallet-Dependent Content for Search Engines
This is the trap that catches the most teams. Your best content, the explainers, the token mechanics, the “how it works” pages, sits behind a “Connect wallet” button. A human connects MetaMask and sees everything. Googlebot never connects a wallet, so it always sees the disconnected state, which is usually a button and a sentence.
I saw this recently with a client who had hidden all 30 of their integration pages, one for each platform you can connect their product to, behind the wallet login. Every one of those pages was a clean programmatic SEO opportunity, targeting searches like “connect [platform],” and not one was indexable. Thirty pages of real demand, invisible to Google and to AI tools, purely because the content only loaded after a wallet connection.
You cannot ask the crawler to authenticate. So separate the two jobs:
- Public, indexable layer: the educational and marketing content that explains what your protocol does. This must render fully for a disconnected visitor, with no wallet required.
- Gated, interactive layer: the actual app functions (swaps, staking, portfolio views) that genuinely need a wallet. These do not need to rank, so it is fine if they stay client-side.
A clean pattern is to give every concept its own indexable URL. Instead of one app route where content appears only after connection, publish a real page for each topic that loads its content server-side, then link into the app for the interactive part. You get the rankings from the public page and keep the app experience intact.
Optimising Core Web Vitals with Heavy Web3 Libraries
Web3 libraries are large. Web3.js can exceed 1MB uncompressed, and once you add wallet SDKs, chain connectors, and a charting library, a “simple” page can ship several megabytes of JavaScript before a user reads a word. That wrecks Largest Contentful Paint and Interaction to Next Paint, two of the metrics Google uses to judge experience.
The mistake I see most often is loading the entire Web3 stack on every page, including the blog and the homepage, where no blockchain call ever happens. There is no reason for a reader of your “what is a rollup” article to download a wallet connector.
A few fixes that move the numbers:
- Load Web3 libraries only where they are used. Marketing pages, blog posts, and docs should ship zero wallet code. Import the heavy libraries on app routes only.
- Lazy-load on interaction. Do not initialise the wallet connector on page load. Trigger it when someone actually clicks “Connect.”
- Prefer Ethers.js or Viem over Web3.js where you have the choice. They are lighter and more modular, so you can import only the functions you need.
- Code-split aggressively. Modern bundlers split your JavaScript per route, so a visitor only downloads what that page requires.
For a deeper structural view of how page experience and content layout feed both rankings and AI retrieval, see my breakdown of content structure for SEO and LLMs.
Technical SEO guides for Web3 implementation
This pillar explains the architecture. Use the specialist guide that matches the issue you find:
- JavaScript SEO for Web3 dApps for client-side rendering and wallet-gated content.
- Server-side rendering for crypto sites for indexable HTML and hybrid app architecture.
- Indexing and crawl management for coverage, sitemaps and crawl budget.
- Robots.txt for crawler access and bot directives.
- llms.txt for Web3 for AI-specific discovery guidance.
- Web3 site structure for AI search for explanatory, machine-readable architecture.
- Internal linking for Web3 for cluster structure and authority flow.
- Redirection management for migrations, rebrands and URL changes.
- Enterprise website migration case study for implementation at scale.
- SEO audit checklist for a complete diagnostic pass.
How to Handle Dynamic Blockchain Content and Duplicate URLs
Once a project starts generating pages from on-chain data, the technical problem shifts from “can Google see this page” to “is Google drowning in near-identical pages.” A token explorer, an NFT marketplace, or a multi-chain dashboard can spin up tens of thousands of URLs, many of them thin or duplicated.
Managing On-Chain Data and Indexation at Scale
On-chain data updates constantly, and naive setups create a fresh URL for every filter, sort order, and query parameter. Search engines then waste crawl budget on parameter variations of the same page instead of your important content.
Control it deliberately:
- Set canonical tags so every variation of a page points to one preferred URL. A token page filtered by date range should canonicalise to the clean token page.
- Use
robotsdirectives and parameter handling to keep low-value parameter URLs out of the index. - Decide what deserves to be indexed at all. Not every auto-generated page should rank. Index the pages with genuine search demand, and noindex the long tail of thin variations.
When tokens, pools, or pages are deprecated, retire those URLs cleanly with redirects so their signals consolidate instead of leaving dead ends for crawlers, something decentralised and immutable hosting makes harder to do after the fact.
Generating Sitemaps Programmatically for Thousands of Pages
When you have thousands of legitimate pages, a hand-built sitemap is not an option. You generate the sitemap from the same data source that builds the pages, so it always reflects what actually exists, and you split it into multiple files of up to 50,000 URLs each.
This is where programmatic SEO and technical SEO meet. Done well, scale becomes an advantage rather than a liability. When I worked with the Web3 payments protocol Bando, we built a programmatic system that produced more than 200 landing pages across chains, brands, and use cases, each with controlled templates, canonical logic, and clean internal linking. Organic traffic rose 308% against the previous quarter and sessions from ChatGPT doubled. The pages scaled because the structure was decided up front, not patched afterwards. If you want the full method, I covered it in programmatic SEO for Web3 and crypto.
A separate but related issue is crawl management: telling Google what to spend its budget on. I go deeper on that in indexing and crawl management for Web3 websites.
A Practical Technical SEO Checklist for Web3 Sites
If you do nothing else, work through this:
- View-source a key page and confirm your core content and metadata are in the raw HTML, not injected later by JavaScript.
- Move marketing pages, blogs, and docs onto traditional hosting or static generation. Keep IPFS and Arweave for assets, not for pages you want ranked.
- Make sure every educational page renders fully for a disconnected wallet.
- Strip Web3 libraries from every page that does not make a blockchain call, and lazy-load them on the ones that do.
- Apply canonical tags across dynamic and parameterised URLs, and noindex thin variations.
- Generate sitemaps from your data source and split them into 50,000-URL files.
- Re-test in Google Search Console with the URL Inspection tool to confirm the rendered page matches what users see.
This is the work that decides whether your content ever gets a chance to rank. The strategy and content can be excellent, but if the crawler cannot reach the page, none of it counts. A technical SEO audit is usually where we start an engagement, because it surfaces exactly these problems, broken rendering, blocked crawlers, duplicate URLs, before they cost you rankings. For teams building on complex Web3 stacks, this is exactly the kind of foundation we put in place before touching content. You can see how we approach SEO for blockchain, crypto and Web3.
How These Technical Factors Affect AI Search Visibility
The same barriers that block Googlebot also block AI crawlers like GPTBot, PerplexityBot, and Google-Extended, and most are less patient with JavaScript than Google is. If a page only renders client-side or hides behind a wallet, these crawlers read an empty shell, and an LLM cannot cite a page it never ingested. The technical fixes in this guide are the entry requirement for AI visibility, not a separate task: clean server-side HTML, wallet-free indexable content, and controlled URLs are what let models retrieve and reference you. One emerging way to guide AI crawlers directly is an llms.txt file, which I explain in llms.txt for Web3 sites. I cover the content-level signals that build on this foundation in LLM SEO and AI visibility factors, and you can test how readable your own site is to AI right now with my free AI visibility checker.
Frequently Asked Questions
Why is my Web3 dApp not showing up on Google?
The most common reason a dApp is invisible to Google is client-side rendering: the page’s content is built by JavaScript in the browser, so the crawler indexes an empty shell. Wallet-gated content and decentralised hosting on IPFS make it worse. Confirm the problem by viewing the page source and checking whether your actual copy appears in the raw HTML.
Can Google crawl content hosted on IPFS or Arweave?
Google cannot resolve IPFS or Arweave protocol URLs directly and reaches the content only through gateway services, which can be slow or time out. For anything you want ranked, host marketing pages and blogs on a traditional server and reserve decentralised storage for assets like documentation or NFT metadata. This hybrid setup is the most reliable approach for technical SEO on Web3 sites.
Does heavy JavaScript hurt SEO for blockchain sites?
Yes. Web3 libraries such as Web3.js can exceed 1MB uncompressed, which damages Core Web Vitals and slows down indexing. Load these libraries only on pages that make blockchain calls, lazy-load the wallet connector on click, and keep blogs and marketing pages free of wallet code entirely.
How do I stop duplicate content from blockchain data and URL parameters?
Use canonical tags to point every filtered or sorted variation back to one preferred URL, and apply noindex to thin or near-identical pages. For sites with thousands of token or NFT pages, generate sitemaps programmatically from your data source so the index reflects only the pages with genuine search demand.
Should Web3 sites use server-side or client-side rendering?
Use server-side or static rendering for any content you want indexed, and keep client-side rendering for the interactive, wallet-dependent parts of the app. The wallet and on-chain features can stay in the browser, but headings, body copy, links, and metadata must exist in the initial HTML response so search engines and AI tools can read them.
Building in Web3 and struggling with sustainable visibility?
This is the approach we use when working on SEO for blockchain and crypto teams.
If you want to discuss your product or protocol, you can book a free strategy session.











