How to show page title on Google with Angular Precomposition?
Asked Answered
R

2

3

Based on superluminary response here I've set up an Angular 1 app without Hashbangs and html5Mode(true) and rely on Google to execute javascript. The page is being indexed by Google but dynamic titles and description tags are not.

My index.html head is the following:

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <base href="/">

    <meta name="author" content="me">
    <meta name="robots" content="index,follow">

    <title ng-bind="meta.title">Temp Title</title>
    <meta name="description" content="{{meta.description}}">

    <!-- Scripts & CSS -->
</head>

The title and description are correctly loaded but they don't display on Google.

How can I do that?

Also does this technique works with Facebook and other social networks? Thank you.

Ryder answered 21/3, 2017 at 14:4 Comment(2)
maybe pre-rendering your pages for crawlers would be more effective, but i'd like to know if there is an easier method.Howie
@Howie Yes I'm trying to assess if it's possible to avoid that approach and end up with a SEO friendly SPA.Ryder
R
0

Actually superluminary response here has the solution. HTML page head must be sent fully resolved by the server.

So in order for this solution to work I was forced to replicate angular routes in the server side and send the info resolved.

Instead of using a plain html view I changed to .ejs and also changed the header to something like this:

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <base href="/">

    <meta name="robots" content="index,follow">

    <script type="text/javascript"> 
        window.title = <%- JSON.stringify(precomposition) %>.title;
    </script> 

    <title ng-bind="title"><%= precomposition.title %></title>
    <meta name="description" content="<%= precomposition.description %>">
    <!-- More meta information -->
    <!-- Scripts & CSS -->
</head>

Now when the website gets a direct hit (initially resolved by the server instead of Angular, always the case for crawlers) I handle the request server side:

//Express route
app.route('/').get(precomposition.render);

//precomposition
exports.render = function (req, res) {
    const precomposition = {title: 'tile', description: 'description'};
    res.locals.precomposition = precomposition;
    res.render('index.ejs');
};

If it's not a direct hit Angular handles the title update (because the other info is not displayed to the user).

It has off course some downsides but Google since October 2015 recommends this approach instead of "_escaped_fragment_ URLs". Also I think it's a lot less resource consuming than the selfhosted pre-render alternatives and cheaper than the paid ones.

Ryder answered 2/5, 2017 at 12:52 Comment(0)
G
0

Why you don't use something like that?

https://github.com/steeve/angular-seo

Guidebook answered 21/3, 2017 at 14:9 Comment(1)
I'm trying to assess if it's possible to avoid that approach and end up with a SEO friendly SPA.Ryder
R
0

Actually superluminary response here has the solution. HTML page head must be sent fully resolved by the server.

So in order for this solution to work I was forced to replicate angular routes in the server side and send the info resolved.

Instead of using a plain html view I changed to .ejs and also changed the header to something like this:

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <base href="/">

    <meta name="robots" content="index,follow">

    <script type="text/javascript"> 
        window.title = <%- JSON.stringify(precomposition) %>.title;
    </script> 

    <title ng-bind="title"><%= precomposition.title %></title>
    <meta name="description" content="<%= precomposition.description %>">
    <!-- More meta information -->
    <!-- Scripts & CSS -->
</head>

Now when the website gets a direct hit (initially resolved by the server instead of Angular, always the case for crawlers) I handle the request server side:

//Express route
app.route('/').get(precomposition.render);

//precomposition
exports.render = function (req, res) {
    const precomposition = {title: 'tile', description: 'description'};
    res.locals.precomposition = precomposition;
    res.render('index.ejs');
};

If it's not a direct hit Angular handles the title update (because the other info is not displayed to the user).

It has off course some downsides but Google since October 2015 recommends this approach instead of "_escaped_fragment_ URLs". Also I think it's a lot less resource consuming than the selfhosted pre-render alternatives and cheaper than the paid ones.

Ryder answered 2/5, 2017 at 12:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.