Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JS SEO

Jecelyn Yeen
October 22, 2019

JS SEO

Javascript Frameworks & SEO

Jecelyn Yeen

October 22, 2019
Tweet

More Decks by Jecelyn Yeen

Other Decks in Programming

Transcript

  1. @JecelynYeen Software Architect Google Developer Expert - Angular - Web

    Technologies Director - NG-MY 2019 - Women Who Code KL
  2. - What is SEO? - How does Googlebot works? -

    Technical SEO for modern frameworks - Best Practices - Resources
  3. Helping Googlebot - Links your pages to each other -

    Googlebot doesn’t click on stuffs, use links! - Do not use hash URLs (/#products) - Exclude low quality / thin content - Create a sitemap
  4. <title>NG-MY 2019: July 06-07</title> <meta name="description" content="NG-MY 2019. Angular Malaysia

    conference. First in Southeast Asia."> Title tag & Meta tags are essential for SEO
  5. <meta property="og:url" content="https://2019.ng-my.org/" /> <meta property="og:description" content="NG-MY 2019..."> <meta property="og:type"

    content="website" /> <meta property="og:title" content="..." /> <meta property="og:image" content="img.png" /> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:image" content="img.png"> Meta tags for social medias
  6. - Angular Title & Meta Service (built in) angular.io/api/platform-browser/Meta -

    Vue (3rd party) github.com/declandewet/vue-meta - React (3rd party) github.com/nfl/react-helmet
  7. export class SpeakerPageComponent { } Example: Angular Set page title

    Update meta tag Inject title & meta services constructor(private title: Title, private meta: Meta) {} ngOnInit() { this.title.setTitle(‘title’); this.meta.updateTag({ name: 'description', content: ‘desc…’ }); this.meta.updateTag({ name: 'twitter:image', content: ‘imgurl’ }); ... }
  8. ngOnInit() { this.meta.updateTag({ name: 'robots', content: ‘noindex’ }); ... }

    export class HiddenPageComponent { } Exclude content from Index Set page title Inject title & meta services constructor(private title: Title, private meta: Meta) {}
  9. Use robots.txt to prevent crawling User-agent: Googlebot Disallow: /private Everything

    under /private will not be crawled. *will not crawl, but might be indexed
  10. Structured Data schema.org <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "Article",

    "headline": "Cook Weisswurst", "name": "How to Cook Weisswurst", "image": { "@type": "ImageObject", "url": "https://www.wikihow.com/images/...jpg", ... }, ... } </script>
  11. User Browser Web Server HTML + JS for client side

    rendering (Not a bot) Request with browser user agent
  12. Googlebot Crawler Web Server HTML + JS for client side

    rendering Dynamic render Complete static html (I am a bot) Request with Googlebot user agent
  13. Dynamic Rendering - It is a workaround! - Tools -

    github.com/GoogleChrome/puppeteer - github.com/GoogleChrome/rendertron - prerender.io/ - Codelabs: goo.gle/rendertron-codelab
  14. Static rendering happens at build-time at build time to produce

    static files. Get meaningful content onto the user's screen faster
  15. Static Prerendering cli build --prod Generate files to dist/ Open

    browser Browse & Save each route as .html Deploy all files to server Generate static html pages = Prerendering Local serve dist/
  16. Static Prerendering cli build --prod Generate files to dist/ Program

    Puppeteer Browse & Save each route as .html Deploy all files to server Automate with Puppeteer Local serve dist/
  17. Puppeteer - Programmable Chrome Browser const puppeteer = require('puppeteer'); (async

    () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); })(); const fs = require('fs').promises; await fs.writeFile('food.html', html, 'utf-8'); await browser.close(); await page.goto('https://ng-my.org/food', { waitUntil: 'networkidle2'}); const html = await page.content();
  18. Static Prerendering cli build --prod Generate files to dist/ Program

    Puppeteer Browse & Save each route as .html Deploy all files to server Find an even easier library to help us! Local serve dist/
  19. Prerendering // prerender-run.js const { prerenderer } = require('prerender-xs'); const

    path = require('path'); const minimalConfig = { routes: ['/', '/route1', '/route2/b'], // all the routes staticDir: path.join(__dirname, '/dist'), // where your SPA located } const data = await prerenderer(minimalConfig); // node prerender-run.js
  20. SSR / Dynamic (puppeteer, rendertron) Static (prerender-spa-plugin) - Rapid changing

    content that always change (e.g. news) - Require a server - Dynamic Rendering is a workaround - SSR increase complexity* - Predictable content (e.g. company site, event site) - Can host in cloud storage (S3, Firebase hosting)
  21. No index when result not found fetch('/api/speakers/jane-doe') .then(res => res.json)

    .then(speaker => { if (!speaker.exists) this.meta.updateTag({ name: 'robots', content: 'noindex' }); });
  22. Page B won’t be indexed // script on page A

    userAgreesGDPRbutton.addEventListener('click', () => { writeCookies('gdpr_agreed', true); }); // script on page B if (!readCookies('gdpr_agreed') { window.location.href='/page-a'; }
  23. Handle feature detection if ('geolocation' in navigator) { // load

    content once we get location info navigator.geolocation.getCurrentPosition(loadContent); } else { // load fallback content } Uh oh, feature supported but rejected
  24. Handle feature detection if ('geolocation' in navigator) { // load

    content once we get location info navigator.geolocation.getCurrentPosition( loadLocalContent, loadFallbackContent); } else { // load fallback content } Load fallback content
  25. Mobile friendly test - Screenshot - Loading issues - Rendered

    HTML https://search.google.com/test/mobile-friendly
  26. SEO Audits - HTTP header responses - Correct meta tags,

    hreflang & descriptive link text - Tap targets sizing - Checking robots.txt - Coming soon: Structured data
  27. Useful resources & references - Headless Chrome: an answer to

    server-side rendering JS sites (link) - Prerendering explained (link) - Get started with dynamic rendering (link) - Google search resources (link) - Rendering on the web (link) - Javascript SEO video series (link) - Technical SEO demystified (link) Office-hours hangouts with the webmaster teams - https://www.google.com/webmasters/connect/