Docs

Contributing

How misomoon.com is built for search and AI answers

This page explains the search choices in the marketing site (apps/landing), so a change to it keeps them. It covers the site's own pages, not the analytics product. Each rule cites the Google page it comes from, with the date the page was last updated and the date we read it.

Google Search, AI Overviews, and AI Mode all rank the same pages from the same index. A page that is easy to crawl and answers its question in the first paragraph does well in all three. Most of what follows comes back to that.

One URL, one question, one answer

Every page targets one question and answers it in the first paragraph under the h1. On a comparison page, that first paragraph is the answer field in apps/landing/src/lib/alternatives.ts. An AI answer quotes a passage it can lift whole, and a reader who arrives from search wants the answer before the detail.

The site has these kinds of pages:

PathBuilt fromQuestion it answers
/CodeWhat misomoon is.
/featuresapps/landing/src/lib/features.tsWhat misomoon does, with a link to the docs page for each feature.
/features/<slug>apps/landing/src/lib/feature-pages.tsOne feature people search for by name, such as heatmaps, with what it shows, how to turn it on, and its limits.
/pricingapps/landing/src/lib/pricing.tsWhat misomoon Cloud costs.
/alternativesapps/landing/src/lib/alternatives.tsHow misomoon compares with the tools a reader knows.
/alternatives/<slug>apps/landing/src/lib/alternatives.tsmisomoon or one other tool, for a reader deciding between them.
/blog, /blog/<slug>, /blog/tag/<tag>The content databasePosts, and the posts on one topic.
/authors/<id>The content databaseWho wrote the posts.
/<slug>The content databaseAny other page, such as a guide.

Publish posts and pages explains the content database and its API.

Comparison pages state facts with sources

Google's spam policies call many similar pages made to rank for similar searches doorway abuse. A page for each competitor turns into that when only the name changes. Each comparison page here has its own table, its own reasons to pick the other tool, and its own switching steps. Every fact about another product carries a source URL and the date someone checked it, and the page prints both as numbered footnotes.

apps/landing/src/lib/alternatives.test.ts keeps it that way. It fails when:

  • a claim has no https source or no valid checked date,
  • a page has no reason to pick the other tool,
  • a description is outside 70 to 160 characters,
  • a tracker size differs from the one in How misomoon compares, or
  • another product's name appears in any file except alternatives.ts, docs/comparison.md, and the README.

The persuasive parts of a page come from the same facts, through apps/landing/src/lib/verdict.ts, so nothing on them is written by hand:

  • The tally counts the table's rows: the ones misomoon does better, the even ones, and the ones the other tool does better.
  • "Why teams switch" shows up to three rows misomoon does better, each with its source. Privacy and price come first, then funnels, revenue, imports and the rest.
  • The weight card says how many times lighter misomoon's Light preset is than the other tracker. It rounds down, and it doesn't show when the gap is under 1.5 times.

apps/landing/src/lib/verdict.test.ts fails when a comparison has fewer than three of these to lead with. Add a sourced row, not a headline.

A page that says when the other tool is the better choice is one a reader can trust. Without that section, the page is an ad, and readers and search engines both treat it like one.

Source: Spam policies for Google web search, updated 2026-08-28, read 2026-10-25. The same page describes scaled content abuse: many pages made to rank, with little value for the reader. Write a post because it answers a question someone asks, not to fill a topic.

Posts name a real author

Google reads who wrote a page from the Article structured data and the byline. Each post carries BlogPosting JSON-LD with the author as a Person, the author's page as url, and the profiles in sameAs. A published post can't be saved without an author, and each author has a page at /authors/<id> with ProfilePage structured data.

Dates are in ISO 8601 with a time zone. datePublished is the first publish. dateModified moves only when the title, description, body, or image changes, and not for a change marked minor. A date that moves for a typo fix tells readers and search engines that the post changed when it didn't.

Source: Article structured data, updated 2026-09-08, read 2026-10-25.

Content written with AI tools is allowed when it is accurate and useful. Content made to rank, at scale, is spam whoever writes it. Read every post before it goes out, and check every number in it.

Source: Using generative AI content, updated 2026-10-01, read 2026-10-25.

Structured data on every page

apps/landing/src/lib/seo.ts builds the JSON-LD, and Seo.svelte prints it with the title, the description, the canonical URL, and the Open Graph tags.

PageTypes
/Organization, WebSite, SoftwareApplication, FAQPage
/featuresCollectionPage, SoftwareApplication, ItemList, BreadcrumbList
/features/<slug>WebPage, FAQPage, BreadcrumbList
/pricingWebPage, SoftwareApplication with an Offer for each plan, FAQPage, BreadcrumbList
/alternativesCollectionPage, ItemList, BreadcrumbList
/alternatives/<slug>WebPage, FAQPage, BreadcrumbList
/blog and topicsBlog or CollectionPage, ItemList, BreadcrumbList
/blog/<slug>BlogPosting, BreadcrumbList
/authors/<id>ProfilePage with a Person, BreadcrumbList
/<slug>WebPage, BreadcrumbList

Structured data describes what the page already shows. A question in FAQPage is a question printed on the page, with the same answer.

A list of posts (the blog, a topic, an author) shows 12 posts a page. Each older page keeps its own canonical URL (?cursor=) and a title of its own, named by the date of its newest post, such as "Blog: posts from 4 March 2026 and before". A cursor the site never handed out answers 404. An author page's description is the bio, cut or padded to 70 to 160 characters.

The sitemap prints only true dates

/sitemap.xml lists the pages built from code, then every published entry that is indexable. It leaves out drafts, entries with noindex, and entries whose canonical points to another site. Each URL has loc, and lastmod only when the site knows the real date:

  • A blog post or page uses its updatedAt.
  • A comparison page uses the newest checked date among its facts.
  • /alternatives uses the newest checked date of any comparison.

Google uses lastmod only when it is consistently accurate, and ignores priority and changefreq, so the sitemap leaves those out. One sitemap holds up to 50,000 URLs or 50 MB. The site is far below that, so it needs no sitemap index.

Source: Build and submit a sitemap, updated 2026-07-08, read 2026-10-25.

The docs site's pages have their own sitemap

misomoon.com also serves /sitemap-docs.xml, which lists every page that docs.misomoon.com builds and nothing else. The docs site has no Worker code, so its robots.txt names that file, and its own /sitemap.xml redirects there. A sitemap on one host may list another host's pages when that host's robots.txt points at it, and such a sitemap holds that host's pages only. That is why misomoon.com keeps two files instead of one. /sitemap-docs.xml answers 404 when PUBLIC_DOCS_URL is unset.

Sources: Build and submit a sitemap, updated 2026-07-08, and Sitemaps & Cross Submits, both read 2026-10-25.

The site has no news sitemap. A news sitemap is for publishers in Google News, lists only articles from the last two days, and holds up to 1,000 of them. A product blog gets nothing from one.

Source: News sitemaps, updated 2025-12-10, read 2026-10-25.

Each page sets max-image-preview:large in its robots meta tag. Google Discover shows a large card only for an image at least 1200 pixels wide, on a page that allows large previews. The site's default image, static/og.png, is 1200 by 630. Give a post its own image of at least 1200 pixels wide. The content API warns when a post has none.

Source: Get on Discover, updated 2026-03-09, read 2026-10-25.

AI answers need nothing extra

AI Overviews and AI Mode use the same crawling, index, and ranking systems as Search. They need no special markup, no AI text file, and no other setup. A page shown in Search can be quoted in an AI answer. The controls are the same as for snippets: nosnippet, data-nosnippet, and max-snippet. Google-Extended in robots.txt controls the use of a page for training Gemini models, and doesn't change Search.

Source: AI features and your website, updated 2025-12-10, read 2026-10-25.

The site allows every crawler in robots.txt and blocks only /api/. Both hosts add Content-Signal: search=yes, ai-input=yes, ai-train=yes, which says in the Content Signals format that search, AI answers, and AI training may all use the pages. A crawler that doesn't read the line ignores it. Pages set max-snippet:-1, so a snippet or an AI answer can quote a passage of any length.

misomoon.com serves the AI text files for both hosts, and docs.misomoon.com redirects its own to them:

  • /llms.txt is a Markdown map in the llms.txt format: the product pages, every docs page linked to its Markdown, the comparisons, and the newest 50 posts. The legal pages and /llms-full.txt sit under ## Optional.
  • /llms-full.txt is that map followed by the plans, the features, every docs page, the legal pages, and the posts in full, with every link made absolute.

Google doesn't use either file. Each costs one route and is built from the same data as the pages, so neither says anything the pages don't.

The docs pages carry their own structured data

Each docs page prints a TechArticle with a BreadcrumbList (docs home, the sidebar section, the page), a canonical URL on docs.misomoon.com, Open Graph tags with the site's 1200 by 630 image, and a text/markdown alternate link to its .md version. Its meta description is the page's first paragraph, cut to the whole sentences that fit in 160 characters.

Every page links to the pages a reader wants next:

  • The footer lists the first five comparisons, the blog, the docs, and the legal pages, so every page links to them.
  • Each comparison page links to the other comparisons, and each claim links to its source.
  • Each post links to its topics, its author, and up to three related posts that share its tags.
  • The features page links each feature to its docs page.
  • Breadcrumbs on every page below the home page link back up the tree.

A topic page with fewer than two posts has noindex, because a list of one post is a thin page. It turns indexable once a second post has the tag.

Fast pages without the weight

Pages render on the server, so a crawler gets the full text without running JavaScript. The comparison data stays on the server, which keeps it out of every page's JavaScript. Content pages come from the data center's cache, and browsers keep them for 60 seconds (Caching). Before a change that adds a script or a large image, check the page's weight in the build output.

Feeds

/feed.xml is an RSS 2.0 feed of the 20 newest posts, with the full text of each. The head of every page links to it, so a feed reader finds it from any URL on the site.

Search every page and heading. ↑ ↓ to move, enter to open.