How can I optimize my dapp for SEOs?

The Internet Computer now supports traditional web crawlers, and dapps running 100% on-chain can be indexed by search engines and their metadata can be read to generate cards on social platforms. This means that any dapp can be searched and found easily, similar to a web2 application.

This is great news for any developers looking to host a dapp and gather more users, viewers, and potentially an ecosystem of their own. 

If you're looking for more information on how best to host a dapp, check out these IC resources:

Once you have a dapp running on the Internet Computer, it's important to be sure that you have all the necessary data needed for webcrawlers to find and present your dapp to others through various channels such as Twitter. 

Important information to keep in mind for metadata can include:

  • Title:The name of the application, the product.
  • Description:Its tag line, its catchy selling phrase.
  • Icon:A square image used to generate the favicons (note the plural).
  • Social image:Another image (ratio 1.9:1) used to generate a card on platforms such as Twitter, Facebook, Discord, LinkedIn, etc.

These static assets must be served by our canister smart contracts, so be sure to set meta data in ​all HTML pages of your application, as well as a web app manifest, and a sitemap.xml. Lastly, you can allow crawlers to view your content by defining a robots.txt.

 

HTML 

In the <head />​​ container of our HTML pages, it is good practice to set not only the <title />​ but also a ​<description />​​ and an<author />.​ It is also important to set the language of the document to one that matches its content. For instance, if you provide meta tags in Spanish, for example, it is useful to also set the document as such.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />

<title>Papyrs</title>
<meta content="Blog on web3" name="description" />

<link href="https://papy.rs" rel="canonical" />
</head>
</html>

 

Open Graph

Open Graph meta tags — or ​og:​ — are snippets of code that control how our applications are displayed when shared on social platform. They control what will be displayed when our URLs are shared on platform such as Facebook, LinkedIn, Discord, etc. 

Some important tags to be conscientious of include:

  1. ​​og:title​: The title of the app or in case of multiple pages, a title related to the page’s content — e.g., in the case of a blog, the particular title of a post.
  2. og:description​: Same as title but for the description.
  3. og:url: The URL of the content. To consolidate connected data, I also apply here the same approach as for the ​canonical​ URLs.
  4. og:type​: Usually a ​website​ for a page or ​article​ in the case of a blog post.
  5. og:image​: An absolute URL to your social image.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Here same HTML tags as previous chapter -->

<meta content="Papyrs" property="og:title" />
<meta content="Blog on web3" property="og:description" />
<meta content="website" property="og:type" />
<meta content="https://papy.rs" property="og:url" />
<meta content="https://papy.rs/images/social-image.jpg" property="og:image" />
</head>
</html>

 

Twitter

Twitter has its own set of meta tags. It is best to also provide these to control how our applications are displayed when shared on this particular platform.

To best render the Summary Cards, it's best to add:

  1. twitter:card​: The type of card — of tweet. Our recommendation is ​"summary_large_image"​
  2. twitter:title​: The title of the product or page.
  3. twitter:description: The tagline or catchy phrase.
  4. twitter:image​: The absolute URL to the social image.
  5. twitter:creator: The Twitter handle of the product or its creator.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Here same HTML tags as previous chapter -->
<!-- Here same og: tags as previous chapter -->

<meta content="summary_large_image" name="twitter:card" />
<meta content="Papyrs" name="twitter:title" />
<meta content="Blog on web3" name="twitter:description" />
<meta content="https://papy.rs/images/social-image.jpg" name="twitter:image" />
<meta content="@PapyrsApp" name="twitter:creator" />
</head>
</html>

 

​Social image

A social image should be provided with an absolute URL, in other words, it should not be provided with an absolute path. Crawlers would not interpret that correctly. We recommend the size 1200x628pixels for optimal dimension across all devices, and to use an old-fashioned image format such as ​png​ or ​jpg​.

<!-- This works -->
<meta content="https://papy.rs/images/social-image.jpg" name="twitter:image" />

<!-- This does NOT work -->
<meta content="/images/social-image.jpg" name="twitter:image" />

 

Favicons / Maskable icons

When providing a favicon, it's important to think about the various device sizes one could encounter. It's first best to provide a ​png​ or ​jpg​ in a square format — e.g., ​1080x1080pixels. We recommend the tool https://realfavicongenerator.net/  to generate a set of data for favicons and theming information. If you'd like, you could provide your own icons in the varying sizes manually - 48x48​, ​72x72​, ​96x96​, ​144x144​, ​192x192​, ​256x256​, ​384x384​ and ​512x512​ pixels. Then copy the icons and the generated data to the static assets of your applications and set the related meta tags to the HTML pages.

<!DOCTYPE html>
<html lang="en">
<head>
<!-- Here same HTML tags as previous chapter -->
<!-- Here same og: tags as previous chapter -->
<!-- Here same twitter: tags as previous chapter -->

<link href="/favicon-32x32.png" rel="icon" type="image/png" />
<meta content="#000000" name="theme-color" />

<link href="/icons/icon-48x48.png" rel="apple-touch-icon" sizes="48x48" />
<link href="/icons/icon-72x72.png" rel="apple-touch-icon" sizes="72x72" />
<link href="/icons/icon-96x96.png" rel="apple-touch-icon" sizes="96x96" />
<link href="/icons/icon-144x144.png" rel="apple-touch-icon" sizes="144x144" />
<link href="/icons/icon-192x192.png" rel="apple-touch-icon" sizes="192x192" />
<link href="/icons/icon-256x256.png" rel="apple-touch-icon" sizes="256x256" />
<link href="/icons/icon-384x384.png" rel="apple-touch-icon" sizes="384x384" />
<link href="/icons/icon-512x512.png" rel="apple-touch-icon" sizes="512x512" />

<link rel="mask-icon" href="/icons/safari-pinned-tab.svg" color="#7888ff" />
<meta name="msapplication-TileColor" content="#ffeed6" />
<meta name="msapplication-config" content="/icons/browserconfig.xml" />
</head>
</html>

While this does the job for most devices, for Android devices it is best to use adaptive icons — also know as “maskable icons” — as well. They display app icons in a variety of shapes across different device models. You can use a tool such as https://maskable.app/editor to best fit any Android devices and export in all various dimensions, similar to above.

 

Web app manifest

The web app manifest is a JSON file that tells the browser about our web application and how it should behave when installed on the user’s desktop or mobile device. It should be provided by your smart contract with the appropriate JSON mime type (application/json).

​Commonly named manifest.webmanifestor ​manifest.json and served from the root of websites, these files contain the same meta information as those specified previously, but can also provide much more, such as shortcuts and screenshots.

<!DOCTYPE html>
<html lang="en">
<head>
<!-- Here same HTML tags as previous chapter -->
<!-- Here same og: tags as previous chapter -->
<!-- Here same twitter: tags as previous chapter -->
<!-- Here same favicons and other info as previous chapter -->

<link crossorigin="anonymous" href="/manifest.webmanifest" rel="manifest" />
</head>
</html>
{
"name": "Papyrs",
"short_name": "Papyrs",
"start_url": "/",
"background_color": "#000000",
"theme_color": "#000000",
"display": "standalone",
"icons": [
{"src": "icons/icon-48x48.png", "sizes": "48x48", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-72x72.png", "sizes": "72x72", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-96x96.png", "sizes": "96x96", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-144x144.png", "sizes": "144x144", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-256x256.png", "sizes": "256x256", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-384x384.png", "sizes": "384x384", "type": "image/png", "purpose": "any"},
{"src": "icons/icon-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "any"},
{
"src": "icons/maskable-48x48.png",
"sizes": "48x48",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-256x256.png",
"sizes": "256x256",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-384x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/maskable-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}

 

Sitemap.xml

​Sitemaps are useful to help search engines understand what pages should be crawled and indexed. The sitemap.xml​ is an XML file, therefore it should be served by the canister with the appropriate mime type (​application/xml​). It should also be referenced within any HTML pages.

<?xml version="1.0" encoding="UTF-8" ?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"
>
<url>
<loc>https://papy.rs/</loc>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
</url>

</urlset>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Here same HTML tags as previous chapter -->
<!-- Here same og: tags as previous chapter -->
<!-- Here same twitter: tags as previous chapter -->
<!-- Here same favicons and other info as previous chapter -->
<!-- Here link to web app manifest -->

<link href="/sitemap.xml" rel="sitemap" type="application/xml" />
</head>
</html>

 

Robots.txt​

At this point everything is in place for search engine and social platform, but crawlers might not yet be able to read these information. To fix this, add a robots.txt​ file at the root of the site to control how they should access all content.

​Assuming we want any crawlers to index all of our app, we can provide such information by targeting all ​User-agent: *and allowing everythingAllow: /.

Then provide the URL to the sitemap and host information.

User-agent: *
Allow: /
Sitemap: https://papy.rs/sitemap.xml
Host: https://papy.rs

 

Updated