SEO Support For Dynamic Generated Data Using Angular Universal

We at work just started re-architecture of our application, so we need SEO support for single page application which we gonna build with Angular 2/4.

Based on R&D on internet we found that angular universal is pretty cool. It solves our problem for server side rendering for static data as well AJAX called data.

But this ajax called data only made available when services are being called at the start of the component(in NgInit more precisely). But when we make changes any further like searching for some products then the dynamically generated data won't be available in view page source hence it won't be available for google bot or other crawlers also.

Angular Universal provides a simple example with server side rendering here.

If somebody has done this before please try and answer.

It would be great if nobody marks it as off topic or spam because I have seen many questions in SO but none of them answers my problem here.

Few work around

Node Version  
NPM version  
Angular 4.2  

Angular Cli   

os: linux x64

Using NodeJS for SSR(Server Side Rendering).

Here's snippet for my server.ts

import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { platformServer, renderModuleFactory } from '@angular/platform-server'
import { enableProdMode } from '@angular/core'
import { AppServerModuleNgFactory } from '../dist/ngfactory/src/app/app.server.module.ngfactory'
import * as express from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';

const PORT = 3000;


const app = express();

let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();

app.engine('html', (_, options, callback) => {
  const opts = { document: template, url: options.req.url };

  renderModuleFactory(AppServerModuleNgFactory, opts)
    .then(html => callback(null, html));

app.set('view engine', 'html');
app.set('views', 'src')

app.get('*.*', express.static(join(__dirname, '..', 'dist')));

app.get('*', (req, res) => {
  res.render('index', { req });

app.listen(PORT, () => {
  console.log(`listening on http://localhost:${PORT}!`);


Just to put up a answer for people who are going through same issue.

In this question I was facing problem getting view source for dynamically generated data, I was working on a ecommerce site that time so, when user do some filtering, the dynamiclly generated data was not getting crawled, What I did was I changed the url of the page on the filters, now if google does want to crawl my page it'll get the latest and real data in source.

Example: If my URL was this and i done some filtering so the url look like this now,coral&offers=51.0-70.0&priceRanges=500,1000&internationaldelivery=IN&page=1

Also adding @Stephen's comment here about SEO of SPA's

Google has deprecated the AJAX escaped_fragment snapshot crawling and soon won't support it: Google is doing a better job at being able to crawl sites that use JavaScript, however single page applications, especially Angular ones are not very search engine friendly. If you want good SEO, abandon your SPA for a more search engine friendly platform.