# SEO

Welcome to one of the mose important pages on NgxShopify docs!

Here we will go through SEO, setup and considerations

# Semi Headless

# What happens when I get crawled?

The starter theme contains a useful snippet of liquid on the theme.liquid file that handles rendering meta titles and descriptions for search when google accesses the page, it is by all definitions Server Side Rendering for the most important tags on the website.

Content however will load as per Angulars standard component lifecycle with the notable exception of the the Frontpage, which has its data rendered on the template to ensure maximium initial page load on typically the heaviest page of most ecommerce websites.

# Infrastructure

One of the most important aspects of SEO through NgxShopify is remembering that you must atleast conform to the standard Shopify permalink structure that is laid out for you.

Thats not to say you can't do what ever you want while you're there however if you venture to far from the sitemap you will find yourself returning a 404 from the Shopify Liquid API, which is a disaster for SEO on your site.

To that end the SemiHeadless Starter theme contains an app-routing-module.ts that contains the permalink structure as Shopify will serve it to your customers.

const routes: Routes = [
  { path: "password", component: LayoutPassword },
  {
    path: "",
    component: LayoutPage,
    children: [
      { path: "", component: PageFront },
      {
        path: "collections",
        component: LayoutEmpty,
        children: [
          { path: "", component: PageCollections },
          { path: "null", component: PageCollections },
          {
            path: ":name",
            component: LayoutEmpty,
            children: [
              { path: "", component: PageCollection },
              { path: "products/:name", component: PageProductParent },
              {
                path: ":name2",
                component: LayoutEmpty,
                children: [
                  {
                    path: "",
                    component: PageCollection
                  },
                  {
                    path: "products/:name",
                    component: PageProductParent
                  },
                  {
                    path: ":name3",
                    component: PageCollection
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        path: "account",
        component: PageAccount,
        children: [
          {
            path: "register",
            component: ComponentRegister
          },
          {
            path: "login",
            component: PageLogin
          },
          {
            path: "activate/:userId/:token",
            component: ComponentActivate
          },
          {
            path: "reset/:userId/:token",
            component: ComponentSet
          },
          {
            path: "",
            canActivate: [AuthGuard],
            component: ComponentAccountHeader,
            children: [
              {
                path: "addresses",
                component: ComponentAddresses,
                canActivate: [AuthGuard]
              },
              {
                path: "orders",
                component: ComponentOrders,
                canActivate: [AuthGuard]
              },
              {
                path: "orders/:id",
                component: ComponentOrder,
                canActivate: [AuthGuard]
              },
              {
                path: "info",
                component: ComponentsAccountInformation,
                canActivate: [AuthGuard]
              },
              {
                path: "",
                component: ComponentDashboard,
                canActivate: [AuthGuard]
              }
            ]
          }
        ]
      },
      { path: "cart", component: PageCart },
      { path: "pages/:page", component: PageParentPage },
      { path: "search", component: PageCollection },
      { path: "products/:name", component: PageProductParent },
      { path: "products/null", component: PageProductParent },
      {
        path: "blogs/:category",
        component: LayoutEmpty,
        children: [
          {
            path: "",
            component: PageBlogs
          },
          {
            path: "tagged/:tags",
            component: PageBlogs
          },
          {
            path: ":post",
            component: PageArticle
          }
        ]
      },
      { path: "styleguide", component: PageStyleGuide },
      { path: "**", component: PageNotFound }
    ]
  }
];
@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      paramsInheritanceStrategy: "always",
      scrollPositionRestoration: "enabled"
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

With the starter template as your base you will not encounter a liquid 404 error.

Why does this happen? In SemiHeadless we use the Shopify Liquid to render most datasources you'd expect to hit in a url, eg: product/product-handle If you were to hit a route on your first visit that was instead giraffe/product-handle/collection You would expect to see a 404, much like any ordinary Shopify website.

# Performance

NgxShopify looks at performance in reasonably absolute terms, choosing to trade off flexibility for speed in some instances and speed for flexibility elsewhere Due to the Liquid as JSON approach to a datasource, SemiHeadless NgxShopify is typically hitting a pre cached liquid file for the vast majority of calls.

Commparison Storefront takes 1-1.5 seconds to retrieve a Product page, with metafields Liquid takes .1-.2 seconds to retrieve a Product page, with metafields

Downloading the JS assets to run angular is handled solely by the Shopify CDN typically serving an Angular Package size of between 300-500kbs in size depending on the complexity of your website.

Want extra performance? Boost your speed by substituting in the new NgxShopify Headless Datasource, coming soon.

We provide flexibile utilities to ensure that you are always loading the correct image size and smallest data objects we can.

# Accessibility

Strong coding convetions and the use of predefined components such as the ngxImg tag can provide you with an easy to maintain search accessibility coverage. We strongly encourage you to break out the components you repeat regularly like buttons into an object that can be reused site wide.