← Ascendy 한국어

frontend

'A global default OG is safe' is a lie — og:url and canonical have no default

· Ascendy Engineering


TL;DR

Source note. Distilled from a frontend-team intake. The public domain ascendy.ai is already public, so it’s used as-is in examples (no secrets or identifiers). Same the-review-caught-it vein as how a fixed bug came back and the rename PR that was the widest PR.

The one place “set a default and move on” breaks

Laying an SEO baseline, most guides say: “Put default Open Graph meta in your nuxt.config.ts head and every page gets a baseline preview. Per-page override later, if needed.”

For most OG fields that’s correct. og:image, og:site_name, a default og:title/og:description — if a page doesn’t set its own, the default fills in sensibly.

But for two fields, it’s a trap: og:url and <link rel="canonical">.

These declare “what URL this page canonically is.” So a default value is meaningless by nature — every page can’t share one. Pin og:url to https://ascendy.ai/ in the global default and never override per page, and about, pricing, privacy, terms, licenses all declare their canonical URL to be ascendy.ai/ (root).

What that actually does

It breaks two ways.

  1. Social previews — share /about or /pricing, and the OG card advertises ascendy.ai/ either way. The link is “wrong,” or at best loses the trust of “is this really that page?”
  2. Search indexing — the more lethal one. One thing to be precise about: rel="canonical" is a signal, not a directive. Google picks the representative URL itself, weighing the canonical tag against other cues (internal links, sitemaps, redirects), and ignores it when the signals conflict. But when <link rel="canonical"> points to root on every page, about/pricing/privacy/terms/licenses all insist “my original is root” — so Google is likely to pick root as the representative and risks dropping the rest from the index. Not a certainty, but you’d be planting, by hand, the very signal that can erase your pages from search while you “set up SEO.”

A Codex review caught this with one line, rg ogUrl pages/ — that no page had an ogUrl or canonical override anywhere. A defect a reviewer can catch with a single grep, and a small illustration of why review earns its keep.

The fix — set both, per page

In Nuxt 3, useSeoMeta takes ogUrl, and canonical is a separate useHead link entry. Set both in the same PR.

// pages/about.vue (same pattern on the other public pages)
const pageUrl = 'https://ascendy.ai/about'
useSeoMeta({
  title: () => t('seo.about.title'),
  description: () => t('seo.about.description'),
  ogTitle: () => t('seo.about.title'),
  ogDescription: () => t('seo.about.description'),
  ogUrl: pageUrl,                              // ← the missing key
})
useHead({ link: [{ rel: 'canonical', href: pageUrl }] })  // ← + canonical for search

18 lines across 6 pages. That’s all it was — a small omission, but with an outsized potential result (“every page risks disappearing from search”).

(Note: hard-coding the prod host is a trade-off in multi-env setups. If dev/staging also need indexing, a dynamic sitemap + runtime config is right. With public pages being prod-only at this stage, pinning prod is correct.)

Takeaways


Authorship & citation: Written by Ascendy Engineering; quotable with attribution. Found something wrong? Let us know via a GitHub issue.


Tags: nuxt, seo, open-graph, canonical, lessons-from-review