Build a complete set of SEO HTML meta tags — title, description, robots, canonical, viewport and more — with a live Google preview. Free, in your browser.

Everything runs in your browser — nothing is uploaded. Fill in the form and copy the generated tags into your page's <head>.

Page details
Aim for :lo–:hi characters so it isn't truncated in search results.
Aim for :lo–:hi characters for the best snippet.
Search result preview

Theme color
Generated tags

Need help?
Found an issue with this tool? Let our team know.
Report an issue

Add this free tool to your own website — copy and paste the code below.

\n\n'; } let lastCode = ''; function render() { const v = values(); applyCounter('title', v.title.length, 50, 60); applyCounter('description', v.description.length, 120, 160); renderSerp(v); lastCode = buildCode(v); codeEl.textContent = lastCode; /* textContent = no XSS */ } /* ----- copy / download ----- */ async function copy(text) { if (!text) { if (window.showToast) window.showToast('warning', T.nothing); return; } try { await navigator.clipboard.writeText(text); } catch (e) { try { const tmp = document.createElement('textarea'); tmp.value = text; document.body.appendChild(tmp); tmp.select(); document.execCommand('copy'); tmp.remove(); } catch (e2) { if (window.showToast) window.showToast('error', T.copy_failed); return; } } if (window.showToast) window.showToast('success', T.copied); } function download() { const v = values(); if (!lastCode) { if (window.showToast) window.showToast('warning', T.nothing); return; } const blob = new Blob([buildDocument(v)], { type: 'text/html;charset=utf-8' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'meta-tags.html'; document.body.appendChild(a); a.click(); setTimeout(() => { URL.revokeObjectURL(a.href); a.remove(); }, 0); if (window.showToast) window.showToast('success', T.downloaded); } /* ----- events ----- */ Object.values(inputs).forEach(el => { el.addEventListener('input', render); el.addEventListener('change', render); }); /* keep color picker and text input in sync */ inputs.themeColor.addEventListener('input', () => { if (inputs.themeColorText) inputs.themeColorText.value = inputs.themeColor.value; }); if (inputs.themeColorText) { inputs.themeColorText.addEventListener('input', () => { const val = inputs.themeColorText.value.trim(); if (/^#[0-9a-fA-F]{6}$/.test(val)) inputs.themeColor.value = val; render(); }); } root.querySelector('[data-mtg-copy]').addEventListener('click', () => copy(lastCode)); root.querySelector('[data-mtg-download]').addEventListener('click', download); root.querySelector('[data-mtg-sample]').addEventListener('click', () => { inputs.title.value = T.sample.title; inputs.description.value = T.sample.desc; inputs.keywords.value = T.sample.keywords; inputs.author.value = T.sample.author; inputs.canonical.value = T.sample.canonical; inputs.lang.value = 'en'; inputs.robotsIndex.value = 'index'; inputs.robotsFollow.value = 'follow'; inputs.viewport.checked = true; inputs.charset.checked = true; inputs.themeColor.value = '#0d6efd'; if (inputs.themeColorText) inputs.themeColorText.value = '#0d6efd'; render(); }); root.querySelector('[data-mtg-reset]').addEventListener('click', () => { ['title', 'description', 'keywords', 'author', 'lang', 'canonical'].forEach(k => { inputs[k].value = ''; }); inputs.robotsIndex.value = 'index'; inputs.robotsFollow.value = 'follow'; inputs.viewport.checked = true; inputs.charset.checked = true; inputs.themeColor.value = '#0d6efd'; if (inputs.themeColorText) inputs.themeColorText.value = '#0d6efd'; render(); }); /* init text mirror for color */ if (inputs.themeColorText) inputs.themeColorText.value = inputs.themeColor.value; render(); })();