Clinia UI

SEO

The tags every Clinia marketing page sets in its head: title, description, languages, sharing image and structured data.

Every marketing page sets the same tags in its <head>, so search engines, agents and social platforms describe Clinia the same way everywhere. The examples below come from clinia.com.

Marketing sites live under clinia.com or on their own subdomain. In the examples, replace https://clinia.com with the address the site is served from: in page URLs, canonical and hreflang links, og:url, WebSite, the sitemap and robots.txt. The Organization values stay on clinia.com on every site, since they describe the company.

TagWhat it doesSet it on
Title and descriptionThe blue link and the text under it in search resultsEvery page
Canonical and hreflangWhich URL counts, and which page is its French or English twinEvery page
Open GraphThe card a shared link shows on LinkedIn, Slack and in messagesEvery page
FaviconThe icon in the tab, in bookmarks and beside the result in searchOnce, in the root layout
Structured dataFacts about Clinia and the page, as JSON-LDOnce for the site, and on every blog post
Robots and sitemapWhich pages search engines index, and where to find themOnce for the site, and on pages kept out of search
llms.txtA short map of the site for agentsOnce, at the site root

Title and description

  • Title: the page's subject, then | Clinia, under 60 characters in all. Search results cut it past that. The home page leads with what Clinia does: "Context Engine for Healthcare AI Agents | Clinia".
  • Description: one or two sentences, 120 to 155 characters, that say what the reader gets from the page. Write it for the reader, not as a list of keywords.
  • One of each per page. Two pages with the same title compete with each other in search.
html
<title>heMTEB: Open-Source Benchmark for Health Retrieval | Clinia</title>
<meta name="description" content="heMTEB extends MTEB with open-source health datasets to test how well AI models retrieve medical information. The first release is CURE." />

Canonical and languages

Each page names its own URL as canonical, absolute and with the trailing slash the site uses. Each English page and its French twin list both versions, and x-default points to the English one for every other language.

html
<link rel="canonical" href="https://clinia.com/" />
<link rel="alternate" hreflang="en" href="https://clinia.com/" />
<link rel="alternate" hreflang="fr" href="https://clinia.com/fr/" />
<link rel="alternate" hreflang="x-default" href="https://clinia.com/" />

Only list a twin that exists. An hreflang link to a page that returns 404 tells search engines the pair is broken.

Open Graph

The sharing image, its size and its alt text, with the title and description repeated for the card. See Sharing images for the image itself.

Use og:type website on the home page and landing pages, and article on blog posts and case studies.

Home and landing pages

html
<meta property="og:type" content="website" />
<meta property="og:title" content="Context Engine for Healthcare AI Agents | Clinia" />
<meta property="og:description" content="Fragmented health data breaks AI. Clinia reconciles it into graph-based context so your healthcare AI agents stay reliable." />
<meta property="og:url" content="https://clinia.com/" />
<meta property="og:site_name" content="Clinia" />
<meta property="og:locale" content="en_CA" />
<meta property="og:locale:alternate" content="fr_CA" />
<meta property="og:image" content="https://clinia.com/og/default.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Clinia" />
<meta name="twitter:card" content="summary_large_image" />

Blog posts and case studies

html
<meta property="og:type" content="article" />
<meta property="og:title" content="heMTEB: Open-Source Benchmark for Health Retrieval | Clinia" />
<meta property="og:description" content="heMTEB extends MTEB with open-source health datasets to test how well AI models retrieve medical information." />
<meta property="og:url" content="https://clinia.com/blog/introducing-hemteb-an-open-source-benchmark-for-health-information-retrieval/" />
<meta property="og:site_name" content="Clinia" />
<meta property="og:locale" content="en_CA" />
<meta property="og:locale:alternate" content="fr_CA" />
<meta property="og:image" content="https://clinia.com/og/hemteb.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="heMTEB: an open-source benchmark for health retrieval" />
<meta name="twitter:card" content="summary_large_image" />

Favicon

The icon tags and the web manifest are set once, in the root layout. See Favicon for the files and the tags.

Structured data

Structured data tells search engines and agents who published the page. Add it as JSON-LD, in a <script type="application/ld+json"> tag.

TypeSet it onWhat it says
OrganizationEvery pageClinia's name, legal name, logo and official profiles
WebSiteEvery pageThe site's name and language
BlogPostingBlog posts and case studiesThe headline, dates, author and image

Organization and WebSite, in the root layout:

json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://clinia.com/#organization",
      "name": "Clinia",
      "legalName": "Clinia Health Inc.",
      "url": "https://clinia.com/",
      "logo": "https://clinia.com/logo.svg",
      "foundingDate": "2016",
      "sameAs": [
        "https://www.linkedin.com/company/clinia/",
        "https://github.com/clinia",
        "https://huggingface.co/clinia",
        "https://www.bcorporation.net/en-us/find-a-b-corp/company/clinia-sant/",
        "https://cliniahealth.applytojobs.ca/"
      ]
    },
    {
      "@type": "WebSite",
      "@id": "https://clinia.com/#website",
      "name": "Clinia",
      "url": "https://clinia.com/",
      "inLanguage": "en-CA",
      "publisher": { "@id": "https://clinia.com/#organization" }
    }
  ]
}

On French pages, set inLanguage to fr-CA.

BlogPosting, on each post:

json
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "heMTEB: Open-Source Benchmark for Health Retrieval",
  "description": "heMTEB extends MTEB with open-source health datasets to test how well AI models retrieve medical information.",
  "image": "https://clinia.com/og/hemteb.png",
  "datePublished": "2024-10-24",
  "dateModified": "2024-10-24",
  "inLanguage": "en-CA",
  "author": { "@id": "https://clinia.com/#organization" },
  "publisher": { "@id": "https://clinia.com/#organization" },
  "mainEntityOfPage": "https://clinia.com/blog/introducing-hemteb-an-open-source-benchmark-for-health-information-retrieval/"
}

The headline is the title without | Clinia, and the image is the post's Article sharing image. When a person wrote the post, set author to a Person with their name.

Robots and sitemap

  • Index the public pages. robots.txt allows every crawler and points to the sitemap.
  • Keep the rest out of search with noindex: preview and staging deployments, thank-you and confirmation pages, and internal pages.
  • List both languages in the sitemap. Each URL names its twin, as the hreflang links do.

robots.txt, at the site root:

txt
User-agent: *
Allow: /
 
Sitemap: https://clinia.com/sitemap.xml

In Next.js, app/robots.ts writes the same file:

ts
// app/robots.ts
import type { MetadataRoute } from "next";
 
export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: "*", allow: "/" },
    sitemap: "https://clinia.com/sitemap.xml",
  };
}

noindex, on each page kept out of search:

html
<meta name="robots" content="noindex" />

Agents

Agents answer questions about Clinia from what they read on its sites. Two things help them get it right:

  • The same facts everywhere. The Organization values, the titles and the descriptions above are what agents quote, so they match across every Clinia site.
  • An llms.txt file at the site root: the site's name, one sentence on what Clinia does, then a list of its key pages, each with a one-line summary. It is a proposed convention that some agents and tools read. This site serves its own at /llms.txt.
md
# Clinia
 
> Clinia builds the context layer for health AI, turning fragmented health data into trusted, reconciled context that AI agents can reason over.
 
## Product
 
- [Context Engine](https://clinia.com/): what the Clinia Context Engine does and who it is for
 
## Research
 
- [heMTEB](https://clinia.com/blog/introducing-hemteb-an-open-source-benchmark-for-health-information-retrieval/): an open-source benchmark for health information retrieval

robots.txt also decides which AI crawlers can read the site. Blocking one keeps Clinia out of that agent's answers.

In Next.js

The metadata API writes the tags above. Set the shared values in the root layout, and each page's own in its generateMetadata:

tsx
// app/[locale]/layout.tsx
import type { Metadata } from "next";
 
export const metadata: Metadata = {
  metadataBase: new URL("https://clinia.com"),
  title: { template: "%s | Clinia", default: "Clinia" },
  openGraph: { siteName: "Clinia", type: "website" },
  twitter: { card: "summary_large_image" },
};
tsx
// app/[locale]/blog/[slug]/page.tsx
import type { Metadata } from "next";
 
export async function generateMetadata({ params }: { params: Promise<{ locale: string; slug: string }> }): Promise<Metadata> {
  const { locale, slug } = await params;
  const post = await getPost(slug, locale);
  return {
    title: post.title,
    description: post.description,
    alternates: {
      canonical: post.url,
      languages: { en: post.urls.en, fr: post.urls.fr, "x-default": post.urls.en },
    },
    openGraph: {
      type: "article",
      locale: locale === "fr" ? "fr_CA" : "en_CA",
      images: [{ url: post.image, width: 1200, height: 630, alt: post.imageAlt }],
    },
  };
}

Render the structured data as a script in the page, and escape < so the JSON can't close the tag:

tsx
<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }}
/>

app/sitemap.ts writes the sitemap, and robots: { index: false } in a page's metadata sets its noindex. For app/robots.ts, see Robots and sitemap.

With Vercel Analytics, <Analytics /> from @vercel/analytics/next sets up window.va inside a Suspense boundary, after the page's own effects have run. A track() call in an effect on page load, such as a page_not_found event, is then dropped without an error, wherever <Analytics /> sits in the layout. Start Vercel's queue before the first call, and the script sends it once it loads:

js
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments) }

Do and Don't

Do

  • Write og:image:alt for the image itself, such as "CURE v1: Cross-lingual Understanding & Retrieval Evaluation".
  • Keep the Organization values the same on every Clinia site, so search engines read one company.
  • Check a new page in Google's Rich Results Test and LinkedIn's Post Inspector before it goes live.

Don't

  • Leave og:image out. Platforms then pick an image from the page, or show none.
  • Mark up what the page doesn't show. Structured data describes the page as readers see it.