The search side: title, description and what it ignores
Start with the most visible pair in search: the title and the meta name="description". The title becomes the blue result link and the browser tab text; the description is the summary suggestion shown below. The word "suggestion" carries all the nuance. Google describes its own behavior plainly: snippets are created primarily from the page content, and the description is only used when it might give the user a more accurate description than the page text itself. In other words, the default is for Google to generate the snippet on its own; your description enters as a candidate, not as guaranteed text. That is why it rewrites the snippet frequently, especially when the description is empty, duplicated, generic or misaligned with the typed query.
Here lives misunderstanding #1: the description is not a ranking factor. It does not push the page up; it influences click-through when Google chooses to use it. Writing a good description is still worth it, it is your chance to sell the click in your own words, but treat it as ad copy, not as a position lever. And do not waste time on meta name="keywords": Google publicly announced in 2009 that it ignores the tag in web search ranking, because it had become spam territory. Filling it in today only hands your keyword list to competitors reading your source.
A numeric example makes the truncation concrete. Suppose a 240-character description. On a desktop SERP, Google usually shows around 155 to 160 characters before the ellipsis; the final 80-odd characters simply do not appear. If your call to action was at the end ("...request a free quote today"), it vanishes. Now flip it: put the hook in the first 120 characters and the cut stops hurting. The arithmetic does not change the description, it changes where you put what matters.
- 2009Google abandons meta keywords
On 21 September 2009, Google’s official blog confirms it does not use the keywords tag in web search ranking, due to abuse.
- 2010Facebook launches Open Graph
At the f8 conference in April 2010, Facebook publishes the Open Graph protocol, creating the og: tags that today become a card on nearly every network.
- 2011Google introduces hreflang
In December 2011, Google adopts rel="alternate" hreflang to relate versions of a page across languages and regions.
- 2012Twitter launches Cards
In June 2012, Twitter (now X) introduces the twitter: tags, falling back to Open Graph when they are missing.
- 2010sJSON-LD becomes preferred
Over the decade, Google comes to recommend JSON-LD as the structured-data format, as the easiest to maintain at scale.
The social side: Open Graph and the scraper cache
Now switch pipelines. When you paste a link into WhatsApp, LinkedIn, Slack or Discord, none of them consults Google’s ranking or reads your description. A scraper visits the page and looks for the Open Graph properties, the protocol Facebook created in 2010 that became a de facto standard. The specification (ogp.me) defines four required properties, and the rest is reinforcement. If those four are correct, you already have a decent card almost everywhere.
| Property | Required? | What it is for |
|---|---|---|
| og:title | Yes | Card title (may differ from the search title). |
| og:type | Yes | Nature of the content: website, article, product, video.other… |
| og:image | Yes | Preview image. Use an absolute HTTPS URL. |
| og:url | Yes | Canonical URL of the content, the object’s permanent identifier. |
| og:description | No | Supporting card text. Without it, some networks leave the card caption blank. |
| og:site_name / og:locale | No | Site name and locale (pt_BR). They refine the display. |
The image is where most people trip. The Open Graph spec does not fix dimensions, but the platforms themselves recommend a large preview around 1200×630 px (~1.91:1 ratio), which fills the card without cropping on Facebook and LinkedIn. Two practical rules prevent most broken cards: serve the image from an absolute HTTPS URL (many scrapers ignore a relative or insecure og:image) and add og:image:alt for accessibility. If you are choosing the file format, the web image formats guide helps you decide between JPEG, PNG, WebP and AVIF, for a social card, a well-compressed JPEG or PNG is the most compatible bet.
Twitter/X cards: the minimum viable and the fallback
X (formerly Twitter) has its own set, prefixed with twitter:. The central tag is twitter:card, which chooses the card format and is the only truly required one. The trick that saves work: when twitter:title, twitter:description and twitter:image are missing, X falls back to the Open Graph equivalents. So the minimum viable setup is a complete Open Graph plus a declared twitter:card. You do not need to duplicate everything, you only need to tell X which format to use.
summary
- Compact card, small square image (~1:1).
- Good when the text is the star.
summary_large_image
- Large image on top, 2:1 ratio (min 300×157, max 5 MB).
- The default for articles and pages with a strong cover.
The twitter:site and twitter:creator tags take @handles, the site’s and the author’s. A common silent mistake is dropping the "@"; the meta tag generator warns when a handle lacks it. On the image: summary_large_image wants a 2:1 ratio, while the "safe" 1200×630 og:image is ~1.91:1. In practice, one good 1200×630 image serves both, X crops a sliver on the sides, no drama. Since X’s card reuses og:image when you do not set twitter:image, you rarely need a second image just for it.
Indexing: canonical, robots and the robots.txt trap
Back to the search engine, three controls decide whether, and how, the page enters the index. They are invisible to the user and decisive for SEO, and each hides a subtlety that takes down whole sites when misunderstood.
- link rel="canonical"
- Points to the preferred version of a page that exists at several URLs. It is a strong signal, not a directive: Google usually honors it but may pick a different URL as canonical if the signals disagree.
- meta name="robots"
- In the page HTML: index/noindex decides whether it can appear in search; follow/nofollow decides whether its links pass signal. It only works if the crawler can read the page.
- X-Robots-Tag
- The same control, but delivered in the HTTP response header. It works for non-HTML files (PDF, image) and to apply noindex on the server without touching the page body.
- robots.txt (Disallow)
- A file at the root asking the crawler NOT to crawl certain paths. It controls crawling, not indexing, and that difference is the trap below.
The canonical holds its own gotcha, misunderstanding #3. It is a hint, not a command. Google treats it as a strong signal of which version you prefer, but keeps the final say: if your page points a canonical at another URL that in turn points back nowhere, if the two pages differ a lot in content, if there are conflicting redirects or hreflang, Google may ignore your choice and canonicalize the URL it judges best. A canonical pointing at the homepage by mistake, a classic in misconfigured templates, can deindex good pages. Before suspecting the canonical, confirm the server returns 200 on the right URL: a page that responds 404 or enters a 301 will not be indexed as you expect. Check the status in the http status checker; the essential HTTP status codes guide covers the nuances of 301, 302 and 404.
The robots.txt × noindex trap, in detail
robots.txt and noindex solve different problems: one controls crawling, the other controls indexing. Specifying noindex inside robots.txt itself is not supported by Google. If you want a URL out of search, the path is to allow crawling and serve noindex via meta robots or X-Robots-Tag; for urgent cases, add the Search Console Removals tool for a temporary suppression while the noindex propagates.
Why the social card stays old after you fix it
The networks’ scraper caches the result by URL. Editing og:image and re-sharing is not enough: as long as the URL is the same, the network returns the cached version. Force a re-read in the platform’s official debugger (Sharing Debugger on Facebook, equivalent validators elsewhere) or, as a last resort, publish under a new URL. It is a social-pipeline failure, not an SEO one, Google is not even part of it.
When Google ignores your canonical
The canonical is a vote, not a law. Google may prefer another URL when the versions’ content diverges, when there are redirect chains, when hreflang points to a different version, when the declared URL is blocked or returns an error, or when most internal links point elsewhere. Check the canonical Google actually chose in Search Console’s URL Inspection, it is not always yours.
meta keywords: why we still find it in templates
It survives by inertia: old CMSs and SEO plugins still emit the field, and some smaller engines once used it. For Google, though, it has been inert since 2009. Keeping it does no harm, but it does no good either, and it exposes your keyword research in the source. Spend that effort on an honest title and description, which is where the click is decided.
Languages and structured data: hreflang and JSON-LD
If your site exists in more than one language, like this one, in pt-BR and en-US, hreflang tells Google which version to show each user. The rule that causes the most errors is reciprocity: the annotations must be bidirectional. Google is blunt: if two pages don’t both point to each other, the tags are ignored. This exists to stop some other site from declaring itself an "alternate version" of your page. So the pt-BR page must list the en-US as an alternate, and the en-US must list the pt-BR back, each also listing itself.
Two requirements finish the setup. First, use the reserved x-default value for the fallback page, the one serving users who match none of your languages. Second, hreflang URLs must be absolute, with the protocol: https://example.com/foo, never //example.com/foo or /foo. You can deliver hreflang in three equivalent ways: link tags in the head, HTTP headers (for PDFs and the like) or annotations in the XML sitemap. Pick one and stay consistent, mixing contradictory signals is a recipe for Google to discard the lot.
The technical head closes with the structured-data layer, which describes the content in machine language (schema.org) and enables rich results. There are three syntaxes, JSON-LD, microdata and RDFa, and for Google all three are fine, as long as they are correct. But there is a stated preference: Google recommends using JSON-LD, as the easiest to implement and maintain at scale and the least error-prone. The practical advantage is that JSON-LD lives in a single script block in the head, separate from the visible HTML, instead of weaving attributes into elements the way microdata does. If you are going to invest in structured data, start with JSON-LD.
In general, Google recommends using JSON-LD for structured data if your site’s setup allows it, as it’s the easiest solution for website owners to implement and maintain at scale.
Google Search Central, Intro to structured data
Who reads what, assembling and auditing the head
Put the two pipelines in a single table and the confusion evaporates. Notice how almost no tag is read by both sides: Open Graph does not move ranking, and title/description do not build the social card.
| Tag | Who it serves | Required? | Real effect |
|---|---|---|---|
| title | Search | Yes | Result link and tab; Google may rewrite it. |
| meta description | Search | No | Snippet candidate, not a ranking factor; rewritten frequently. |
| meta keywords | No one (at Google) | No | Ignored since 2009. Safe to omit. |
| link canonical | Search | No | Preferred-URL hint; Google may pick another. |
| meta robots | Search | No | index/noindex and follow/nofollow, only if the page is crawlable. |
| link hreflang | Search | No | Per-language version; requires reciprocity and x-default. |
| og:title / og:image / og:url / og:type | Social | Yes (for the card) | Build the card; do not affect ranking. |
| twitter:card | X (social) | Yes (on X) | Card format; the rest falls back to og:. |
| viewport / charset | Browser | Yes | Rendering and mobile-friendliness (indirect for SEO). |
Now worked example #1: a real head, full of common mistakes. Each problem line is commented.
<!-- HEAD COM PROBLEMAS / PROBLEM HEAD -->
<title>Home</title> <!-- generico: sem palavra-chave, o Google reescreve -->
<meta name="description" content="" /> <!-- vazia: o Google gera o snippet do conteudo -->
<meta name="keywords" content="tenis, comprar, barato, promocao" /> <!-- ignorada desde 2009 -->
<meta name="robots" content="noindex" /> <!-- e a pagina esta com Disallow no robots.txt (!) -->
<link rel="canonical" href="/produtos/123" /> <!-- URL relativa: fragil -->
<meta property="og:image" content="/img/capa.jpg" /> <!-- relativa, sem og:title/og:type/og:url -->What each mistake causes: the "Home" title says nothing, so Google builds its own; the empty description hands the snippet to the algorithm; meta keywords is dead weight; the noindex + Disallow-in-robots.txt pair is the worst of all, because the crawler cannot fetch the page, it never reads the noindex, and the page stays indexed by URL alone, with no description; the relative canonical is fragile and may be misread; and the relative og:image, with no og:title, og:type or og:url, produces a social card with no image and no title. Now worked example #2: the same head, corrected and commented, covering SEO, Open Graph, X, canonical and hreflang.
<!-- ===== Documento (navegador, nao o Google) ===== -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- ===== Busca: o buscador le isto ===== -->
<title>Contraste de cor na WCAG 2.2: como medir AA e AAA</title>
<meta name="description" content="Como calcular a razao de contraste e passar nos limiares AA e AAA da WCAG 2.2, com exemplos e formula." />
<link rel="canonical" href="https://exemplo.com/guias/contraste" />
<meta name="robots" content="index, follow, max-image-preview:large" />
<!-- ===== Versoes por idioma: reciprocas, absolutas, com x-default ===== -->
<link rel="alternate" hreflang="pt-BR" href="https://exemplo.com/pt/guias/contraste" />
<link rel="alternate" hreflang="en-US" href="https://exemplo.com/en/guides/contrast" />
<link rel="alternate" hreflang="x-default" href="https://exemplo.com/en/guides/contrast" />
<!-- ===== Open Graph: WhatsApp, Facebook, LinkedIn, Slack, Discord ===== -->
<meta property="og:title" content="Contraste de cor na WCAG 2.2" />
<meta property="og:description" content="Limiares AA/AAA e como medir a razao de contraste." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://exemplo.com/guias/contraste" />
<meta property="og:image" content="https://exemplo.com/og/contraste.png" /> <!-- absoluta, HTTPS, ~1200x630 -->
<meta property="og:image:alt" content="Texto sobre fundo com a razao de contraste destacada" />
<meta property="og:site_name" content="Exemplo" />
<meta property="og:locale" content="pt_BR" />
<!-- ===== X (Twitter) Card: so o card e os handles; o resto cai no og: ===== -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@exemplo" />
<meta name="twitter:creator" content="@autora" />
<!-- ===== Dados estruturados: JSON-LD, o formato que o Google recomenda ===== -->
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article",
"headline": "Contraste de cor na WCAG 2.2",
"inLanguage": "pt-BR" }
</script>An honest caveat: the meta tag generator produces the search block (title, description, canonical, robots), the Open Graph and the X tags, the core that changes on every page. The charset, viewport, hreflang and JSON-LD in the example above you add by hand (or your framework injects them), because they depend on the whole site’s structure, not on a single page. Generate the core here and paste it into your head:
- Unique, descriptive title, with the essentials in the first ~60 characters.
- Honest description with the hook up front, knowing Google may rewrite it.
- Absolute canonical pointing at the URL that returns 200.
- To remove from search: allow crawling and serve noindex (never just a robots.txt Disallow).
- Open Graph with the four required (og:title, og:type, og:image, og:url) and an absolute HTTPS og:image.
- twitter:card declared; handles with "@".
- Reciprocal, absolute hreflang with x-default, if the site is multilingual.
- After publishing: re-scrape the URL in the network debugger to clear the card cache.
Frequently asked questions
Why did Google change my title and description?
Does meta keywords still help SEO?
I blocked the page in robots.txt and it is still on Google. Why?
Is the canonical an order to Google?
Do I need both og: and twitter: tags?
I shared the link and the image is missing or outdated. How do I fix it?
What is the ideal title and description length in characters?
Think per pipeline. The search engine reads title, description, canonical, robots and hreflang, it rewrites the snippet frequently, treats the description as a source (not a ranking factor), has ignored keywords since 2009 and treats the canonical as a hint. Social networks read Open Graph, and X uses twitter:* with a fallback to og:, caching the card by URL. The two biggest traps: blocking in robots.txt does not remove from the index (allow crawling and use noindex), and fixing an og: does not refresh the card without a re-scrape. Assemble the core in the meta tag generator and add charset, viewport, hreflang and JSON-LD by hand.
Sources & references
- The Open Graph protocol (ogp.me)
- Google Search Central, How to write meta descriptions / snippets
- Google Search Central Blog, Google does not use the keywords meta tag (2009)
- Google Search Central, Block indexing with noindex (robots.txt × noindex)
- Google Search Central, Consolidate duplicate URLs (rel=canonical)
- Google Search Central, Localized versions (hreflang, x-default)
- X, Cards markup (summary / summary_large_image)