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:
| Path | Built from | Question it answers |
|---|---|---|
/ | Code | What misomoon is. |
/features | apps/landing/src/lib/features.ts | What misomoon does, with a link to the docs page for each feature. |
/features/<slug> | apps/landing/src/lib/feature-pages.ts | One feature people search for by name, such as heatmaps, with what it shows, how to turn it on, and its limits. |
/pricing | apps/landing/src/lib/pricing.ts | What misomoon Cloud costs. |
/alternatives | apps/landing/src/lib/alternatives.ts | How misomoon compares with the tools a reader knows. |
/alternatives/<slug> | apps/landing/src/lib/alternatives.ts | misomoon or one other tool, for a reader deciding between them. |
/blog, /blog/<slug>, /blog/tag/<tag> | The content database | Posts, and the posts on one topic. |
/authors/<id> | The content database | Who wrote the posts. |
/<slug> | The content database | Any 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
httpssource 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.
| Page | Types |
|---|---|
/ | Organization, WebSite, SoftwareApplication, FAQPage |
/features | CollectionPage, SoftwareApplication, ItemList, BreadcrumbList |
/features/<slug> | WebPage, FAQPage, BreadcrumbList |
/pricing | WebPage, SoftwareApplication with an Offer for each plan, FAQPage, BreadcrumbList |
/alternatives | CollectionPage, ItemList, BreadcrumbList |
/alternatives/<slug> | WebPage, FAQPage, BreadcrumbList |
/blog and topics | Blog 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.
/alternativesuses 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.
Images large enough for Discover and link previews
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.txtis 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.txtsit under## Optional./llms-full.txtis 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.
Links that hold the site together
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.