ngx-meta icon indicating copy to clipboard operation
ngx-meta copied to clipboard

dynamically added meta tags does not recognize facebook

Open mistrynilesh opened this issue 7 years ago • 54 comments

I'm submitting a ... (check one with "x")

[ ] Support request => <!-- Please check the repository for a similar issue or PR before submitting -->

Current behavior

Expected/desired behavior

Minimal reproduction of the problem with instructions

import { MetaService } from '@ngx-meta/core';
import { FirstService } from './first.service';

export class FirstComponent {
      firstObj : any = {};

     constructor(private _metaService: MetaService,
                        private _firstService: FirstService) {}
      
     ngOnInit() {
             this._firstService.getQuestionOfTheWeek(0).subscribe(
                  res => firstObj = res,
                  error => this.errorGetRequest(error),
                  () => this.successGetRequest()
              );
       }

    successGetRequest(){
            this._metaService.setTag('og:description', this.firstObj .Desc);
            this._metaService.setTag('og:image', this.firstObj .ImageURL);
     }

}

What is the motivation / use case for changing the behavior?

Meta tag are getting added it is visible in the chrome developer tool but facebook does not recognize.

Environment

  • Angular version: 4.0.0
  • Browser:
  • [ ] Chrome (desktop) version XX
  • [ ] Chrome (Android) version XX
  • [ ] Chrome (iOS) version XX
  • [ ] Firefox version XX
  • [ ] Safari (desktop) version XX
  • [ ] Safari (iOS) version XX
  • [ ] IE version XX
  • [ ] Edge version XX
  • For Tooling issues:
  • Node version: XX <!-- run node --version -->
  • Platform:
  • Others:

mistrynilesh avatar Nov 07 '17 10:11 mistrynilesh

related to https://github.com/fulls1z3/ngx-meta/issues/101

this is because (i believe) the components code are executed on the client side and not at server rendering.

Perhaps this could work? https://github.com/angular/universal#universal-gotchas

gianpaj avatar Nov 10 '17 20:11 gianpaj

@gianpaj I used server side rendering page but still not working. When I am doing view source on browser developer tool than meta tags are available. facebook Sharing Debugger doesn't shows OG tags.

mistrynilesh avatar Nov 16 '17 07:11 mistrynilesh

As mentioned in #101 , I used https://github.com/angular/universal-starter

How are you starting the server? I transpile/build it with npm run build:ssr and then start the server.js in the dist folder with npm run serve:ssr.

I have a very similar code:

export class ItemComponent implements OnInit {

  constructor(
    private route:         ActivatedRoute,
    private itemsService:  ItemsService, // my service
    private router:        Router,
    private readonly meta: MetaService
  ) { }

  ngOnInit() {
    this.route.params.subscribe((data: any) => this.itemsService.getItem(data.id)
      .subscribe((item: Item) => {
        this.item = item;
        this.meta.setTag('og:type', 'product');
        this.meta.setTag('og:image', item.photo);
...

gianpaj avatar Nov 16 '17 08:11 gianpaj

@gianpaj, Thanks.

I am also using default values to set OG tags-

export function metaFactory(): MetaLoader {
  return new MetaStaticLoader({
    pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
    pageTitleSeparator: ' - ',
    applicationName: 'Tour of (lazy/busy) heroes',
    defaults: {
      'og:title': 'Mighty mighty mouse',
      'og:description': 'Mighty Mouse is an animated superhero mouse character',
      'og:image': 'https://d2y8liyagvllvg.cloudfront.net/images/website/nclexqow/20170801.png',
      'og:type': 'website',
      'og:locale': 'en_US',
      'og:locale:alternate': 'en_US,nl_NL,tr_TR'
    }
  });
}
 MetaModule.forRoot({
      provide: MetaLoader,
      useFactory: (metaFactory)
    }),

"og:image" rendered properly but "og:description" and "og:title" doesn't works. not showing facebook debugger.

mistrynilesh avatar Nov 16 '17 10:11 mistrynilesh

I still have the same problem aswell, just like I mentioned here: https://github.com/fulls1z3/ngx-meta/issues/101#issuecomment-337358565

I think the reason its working for @gianpaj is simply timing, the Facebook crawler has a really low timeout, and for very basic apps such as the universal-starter, the time it takes to load the item in ngOnInit is probably fast enough for it to work, but if the loading time is slightly longer, then the Facebook crawler will get a timeout before the item has been loaded.

What we need is a router guard that collects the needed data from the server before activating the route, which will force the Facebook crawler to wait for that.

However, the only way I know about to do this in ngx-meta is to use a backend service similar to the ngx-translate example provided. But, it seems that ngx-meta can only provide parameters with a fixed value to that backend service, from what I understand, not dynamic values like route ID's, etc.

If I'm wrong in that assumption then I would be very happy if someone can provide a howto on how to acheive what we need.

linusbrolin avatar Nov 24 '17 12:11 linusbrolin

I don't think that's true. I don't know the underlying reasons why exactly it works, but my SSR server runs properly and renders the correct meta-tags in the HTML. View the source of this page for example: https://givebox.xyz/item/H1-ybixCZ

The og:image, og:url,og:title (and title) are dynamically generated.

I think you need to make sure you are running something like npm run build:ssr and npm run serve:ssr.

See the package.json https://github.com/angular/universal-starter/blob/master/package.json#L24

gianpaj avatar Nov 24 '17 13:11 gianpaj

I am running a proper aot build with angular-cli. When and how do you collect the correct image url for the og:image tag? Because I can get the og:title to be set to what it should, but the og:image tag is simply not being set, despite the fact that I have created a router guard specifically for this that sets both the og:title and the og:image at the same time from the same data.

Edit: Some source code example on how you set the og:image tag from dynamic data would be welcome.

Edit2: I also want to clarify that I can get the og:image tag to work if I use the defaults, or if I specify a manual value, like in @mistrynilesh example. It is only when the image url is retrieved dynamically that it doesn't work. But the og:title does work, so it makes very little sense.

Edit3: Here is a small code example of a route guard that collects the data and sets the tags, before activating the route:

@Injectable()
export class ProductMetaGuard implements CanActivate {
  constructor(private _platformLocation: PlatformLocation,
              private _productsService: ProductsService,
              private readonly meta: MetaService) {}

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return Observable.create((observer: any) => {
      let url: string = state.url;
      let id: string = next.params['id'];

      this._http
        .get(environment.apiUrl + '/products/' + id)
        .map((res: Response) => res.json())
        .subscribe(
          (val: Product) => {
            let metaSettings: any = (next && next.data && next.data['meta'])
              ? next.data['meta']
              : {};

            if (val && val.title) {
              metaSettings.title = val.title;

              if (val.image && this._platformLocation && this._platformLocation['location']) {
                metaSettings['og:image'] = this._platformLocation['location'].origin + '/images/products/' + val.image;
              }
            }

            this.meta.update(url, metaSettings);

            return observer.next(true);
          },
          (err: any) => {
            return observer.error(err);
          }
        );
    });
  }
}

It sets the og:title properly, but it does not set the og:image properly. In the browser, the og:image is set, but not when I view source. But og:title is set on both.

I do believe it might be platformLocation that screws it up. However, how do I get the origin path during server rendering? I do not want to hardcode a path, since the origin is dynamic.

linusbrolin avatar Nov 24 '17 19:11 linusbrolin

my component class implements OnInit (see https://github.com/fulls1z3/ngx-meta/issues/118#issuecomment-344852631). I've never used or heard of CanActivate. Hopefully somebody can guide you in the right direction

gianpaj avatar Nov 24 '17 21:11 gianpaj

CanActivate is used in the router, as a way to determine if a route is allowed or not, before the component is rendered.

As an update to the issue here, PlatformLocation was the reason that the image does not show up for me. So for now I'm gonna have to live with hardcoding the image paths and just retrieve the filename itself from the server.

I still wish there was a way to do this kind of thing using the ngx-meta router MetaGuard, instead of having to either create my own custom router guard, or make calls in OnInit. As it is now, I can only use the ngx-meta MetaGuard for non-dynamic content.

linusbrolin avatar Nov 25 '17 16:11 linusbrolin

Any update on this issue? I'm also encountering the same issue @linusbrolin reported when the tags are dynamically retrieved from an API rather than being hard-coded. @linusbrolin did you end up resolving your issue?

cahkee avatar Jan 09 '18 04:01 cahkee

@cahkee No, not really. I'm still hard-coding the paths and then use an API to retrieve the filenames. It's ugly, but works for now.

linusbrolin avatar Jan 16 '18 12:01 linusbrolin

@gianpaj can you share your full code for meta update because am getting error in .subscribe((item: Item) => { can't find name Item am also using same Repo from https://github.com/angular/universal-starter and ngx-meta

  1. if i update manually its work --- this.meta.setTag('og:image', 'cAngulsadasdar 4 meta service');
  2. but when i update after API call its not reflected in view source(Cntrl + U) --- this.meta.setTag('og:description', res[i].DocDesc);. any one help me out from this

chozharajan avatar Mar 14 '18 07:03 chozharajan

@chozharajan my code is like https://github.com/fulls1z3/ngx-meta/issues/118#issuecomment-344852631

I don't understand the error you're mentioning: can't find name Item.

Maybe open a StackOverflow question with the code, error message, or even better, a repo to reproduce, and the link to the SO question, and I'll try to help.

gianpaj avatar Mar 14 '18 12:03 gianpaj

@gianpaj thanks for your kind replay. can you share your full code. so it's helpful to build my app. because am also using same as your project. hlp me out my main issue is ---(when i update after API call its not reflected in view source(Cntrl + U))

chozharajan avatar Mar 14 '18 12:03 chozharajan

Reading through all the conversation, the result is not exactly clear. Here is what I think everything above means: to make this work with Facebook it is necessary to:

  • Use server-side rendering
  • arrange things such that routing waits for the data for the meta-tags
  • ... and thus that the meta-tags end up already populated in the <head> of the statically served prerendered content

Is that correct?

kylecordes avatar Mar 14 '18 14:03 kylecordes

@kylecordes If the content you want to use for the facebook meta-tags is dynamically collected via an api, based on the id and other variables you get from the route, then yes.

linusbrolin avatar Mar 14 '18 15:03 linusbrolin

Hi, finally my project work well in local. but once deployed in server. i got view source (cntrl + U) but meta update not happening. i used npm run build:prerender cmd for build the project my reference Repo. and i placed dist/browser files in root directory. here is my project Link. so how to make meta update possible. NOTE: in local am getting meta update for npm run build:ssr cmd. i think am wrongly doing the build cmd. so how to deploy the universal project in IIS server. thanks in advance

chozharajan avatar Mar 27 '18 11:03 chozharajan

Hi, how do you do to work well? do you use canactive to set meta before render??

canpalte avatar Jul 03 '18 06:07 canpalte

@kylecordes, @linusbrolin, any update on this issue? have you been able to find an alternative? My issue is the same as the original problem explained in the ticket. As long as the static content is provided, it appears in facebook crawler. Any dynamic content coming from a http api never appears in the crawler.

bharath-holla avatar Jul 25 '18 07:07 bharath-holla

@bharath-holla Yes, we had to do what I wrote above. Server-side render the pages so that Facebook can pick up the fields. In our case it is very slowly changing content so we did server side pre-rendering on a schedule. If your data is changing frequently,instead you would do server-side rendering on demand. There's plenty to read about angular Universal to make this happen, but the net result is you'll be serving HTML with all of the data already populated, which Facebook can parse to get its fields.

kylecordes avatar Jul 25 '18 19:07 kylecordes

@kylecordes, Thanks, and even we found a similar solution yesterday. We modified server.ts to make a backend call and populated the index.html contents before issuing it to the renderer. And with that Facebook started to pickup the contents that renderer provided and tags started to appear in the FB Sharing Debugger. Thanks anyway.

bharath-holla avatar Jul 26 '18 04:07 bharath-holla

HI, @bharath-holla can you please share the changes you made in server.ts as I'm stuck with this issue for quite while now.

ishan123456789 avatar Oct 01 '18 18:10 ishan123456789

@bharath-holla @ishan123456789 I'm also stuck on this, please are you able to share your solution. My meta tags are showing fine when viewing page-source, but not coming through via Facebook.

thecoconutstudio avatar Jan 05 '19 16:01 thecoconutstudio

@thecoconutstudio not able to get it fixed for a while now. Really depressing problem.

ishan123456789 avatar Jan 05 '19 16:01 ishan123456789

@ishan123456789 @thecoconutstudio Somehow the emails got filtered out and I never observed these comments from both of you.

The below code is of course the most horrible hack, but it worked for me when no other solution on net was working. Till Angular team provides a fix, we decided to go with this.

Here's my partial code.

//all imports
enableProdMode();

export const app = express();

const mysql = require('mysql');
const httpRequest = require("request");
// all other consts

app.engine('html', ngExpressEngine({
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
}));
//all other piece of code in server.ts

app.get('/*', (req, res) => {
  res.render('index', {req, res}, (err, html) => {
    if (html) {
        
        //console.log(html);
        // This is where you get hold of HTML which "is about to be rendered"
    
        // after some conditional checks make a HTTP call
        let url = 'http://....';
        httpRequest.get(url, (error, response, body) => {
                        if(error) {
                            return console.log(error);
                        }
                        const respBody = JSON.parse(body);
                        if(respBody){
                              html = html.replace(/\$TITLE/g, respBody.title);
                              html = html.replace(/\$DESCRIPTION/g, respBody.description);
                              html = html.replace(/\$OG_META_KEYWORDS/g, respBody.metaKeywords);
                              html = html.replace(/\$OG_META_DESCRIPTION/g, respBody.metaDescription);
                              html = html.replace(/\$OG_DESCRIPTION/g, respBody.ogDescription);
                              html = html.replace(/\$OG_TITLE/g, respBody.ogTitle);
                              html = html.replace(/\$OG_IMAGE/g, respBody.img);
                              html = html.replace(/\$OG_SITE/g, respBody.ogSite);
                        }
                        res.send(html);
            });
     }
  }
}

And in index.html, create template values as below:

     
    <title>$TITLE</title>

    <meta name="description" content="$DESCRIPTION"/> 
    <meta name="keywords" content="$OG_META_KEYWORDS" />
    <meta name="metaDescription" content="$OG_META_DESCRIPTION"/> 
    <meta name="metaKeywords" content="$OG_META_KEYWORDS" />
    <meta property="og:title" content="$OG_TITLE" />
    <meta property="og:description" content="$OG_DESCRIPTION" />
    <meta property="og:site_name" content="$OG_SITE" /> 
    <meta property="og:type" content="website" />	
    <meta property="og:image" content="$OG_IMAGE" />

bharath-holla avatar Jan 07 '19 11:01 bharath-holla

Depressing was a good word for it. Has anyone else found a working solution? If not, I'll look into the @bharath-holla (I would need to hack it further for it to work for my needs) Thanks!

matbalazsi avatar Jan 15 '19 22:01 matbalazsi

I am facing this problem as well. Anyone got a better working solution for this?

stevesaw avatar Apr 15 '19 07:04 stevesaw

@bharath-holla , can you please provide me with your source code?

maseranw avatar May 13 '19 19:05 maseranw

@bharath-holla's solution is really the best I've managed to find after 3 days of searching and experimenting with different solutions. Thanks!

KateDobrilko avatar Jun 02 '19 13:06 KateDobrilko

im still unable to implement it, can you provide will full server.ts imports ?

maseranw avatar Jun 02 '19 14:06 maseranw

This it's mi PoC, I add validations for get the params, and I add a promise depending on params. I know this code can improve, but it's a PoC

"use strict";

import "zone.js/dist/zone-node";

import * as express from "express";
import { join } from "path";

// SEO
const url = "YOUR_URL_API";
const url_img = url + "/img";
const api_url = url + "/api";

// Express server
const app = express();

// Http Request
const request = require("request-promise");

const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), "dist/browser");

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {
  AppServerModuleNgFactory,
  LAZY_MODULE_MAP,
  ngExpressEngine,
  provideModuleMap
} = require("./dist/server/main");

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine(
  "html",
  ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [provideModuleMap(LAZY_MODULE_MAP)]
  })
);

app.set("view engine", "html");
app.set("views", DIST_FOLDER);

// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get(
  "*.*",
  express.static(DIST_FOLDER, {
    maxAge: "1y"
  })
);

// All regular routes use the Universal engine
app.get("*", (req, res) => {
  var seo: any = {
    title: "YOUR DEFAULT TITLE",
    description:
      "DEFAULT DESCRIPTION",
    image: "YOUR DEFAUL ROUTE IMAGE"
  };
  res.render("index", { req, res }, async (err, html) => {
    const params = req.params[0];
    if (params.indexOf("talento/") > -1) {
      let id = params.split("/");
      id = params[params.length - 1];
      id = Number(id);
      if (!isNaN(id) || Math.sign(id) > 0) {
        const talent = await getTalent(id);
        seo.title = talent.name;
        seo.description = strip_html_tags(talent.description);
        seo.image = `${url_img}/${talent.image}`;
      }
    }
    html = html.replace(/\$TITLE/g, seo.title);
    html = html.replace(/\$DESCRIPTION/g, strip_html_tags(seo.description));
    html = html.replace(/\$OG_DESCRIPTION/g, seo.description);
    html = html.replace(/\$OG_TITLE/g, seo.title);
    html = html.replace(/\$OG_IMAGE/g, seo.image);
    res.send(html);
  });
});

// Start up the Node server
app.listen(PORT, () => {
  console.log(`Node Express server listening on http://localhost:${PORT}`);
});

function strip_html_tags(str) {
  if (str === null || str === "") {
    return false;
  } else {
    str = str.toString();
    return str.replace(/<[^>]*>/g, "");
  }
}

async function getTalent(id): Promise<any> {
  try {
    const options = {
      uri: `${api_url}/services/${id}`,
      json: true
    };
    const res = await request(options)
      .then(repos => {
        return repos.response;
      })
      .catch(err => {
        return err;
      });
    return res;
  } catch (err) {
    return err;
  }
}


MikeG96 avatar Aug 11 '19 15:08 MikeG96

@bharath-holla I changed my server.ts like your code but it cant update meta tags, view source doesnt shows new metatags value Screen Shot 2019-09-30 at 20 40 36

Ilyoskhuja avatar Sep 30 '19 16:09 Ilyoskhuja

@bharath-holla I changed my server.ts like your code but it cant update meta tags, view source doesnt shows new metatags value Screen Shot 2019-09-30 at 20 40 36

Because, this is only for response in server-side

MikeG96 avatar Sep 30 '19 16:09 MikeG96

@MikeG96 I want that when I get responce from backend api it will change meta tags and show in "view source page", my app showed changed metatags in "inspect" view, but in "view source page" doesnt changed, and in facebook or other messangers shows link without any updated metatags.

Ilyoskhuja avatar Sep 30 '19 16:09 Ilyoskhuja

Do you have any solution for shows updated meta tags on facebook or other messengers ?

Ilyoskhuja avatar Sep 30 '19 16:09 Ilyoskhuja

Do you have any solution for shows updated meta tags on facebook or other messengers ?

This is an example of the "dirty solution" if you have your backend in JS https://github.com/fulls1z3/ngx-meta/issues/118#issuecomment-520235511

For Angular, you need update metas with a service, docs: https://angular.io/api/platform-browser/Meta

MikeG96 avatar Sep 30 '19 16:09 MikeG96

@MikeG96 My backend asp.net core 2.1, I can update my meta tags but when I open "view source page" from console it doesnt shows updated meta tags, and when i share my link in facebook also doesnt shows updated meta tags Screen Shot 2019-09-30 at 20 40 36 Screen Shot 2019-09-30 at 21 50 33

Ilyoskhuja avatar Sep 30 '19 17:09 Ilyoskhuja

Worked as expected @MikeG96 @bharath-holla, was out of nowhere but this small forum helped me solve the nightmare of 2 days. Just to help @Ilyoskhuja, make sure you have the correct route setup in your server.ts file and also check if there are multiple res.send() or res.render() blocks in your app.get(*).

Thanks with regards, Praveen Thirumurugan.

ghost avatar Oct 24 '19 07:10 ghost

I already fixed, my problem was in prerendering.

Ilyoskhuja avatar Oct 24 '19 09:10 Ilyoskhuja

I already fixed, my problem was in prerendering.

i have the same exact problem as yours. I can update the meta tags, shown in inspector, but nowhere to be seen in view source (ctrl+u) how did you solve this?

rasyad avatar Dec 17 '19 03:12 rasyad

@rasyad You should check your prerendering code especially with backend part

Ilyoskhuja avatar Dec 17 '19 04:12 Ilyoskhuja

Has anyone solved this issue ?, managing to publish a link on facebook linkedin and that these platforms recognize the og tags corresponding to each route?

kasius avatar Mar 17 '20 20:03 kasius

Hello everyone, after doing more research and seeing that my "solution" mentioned above was not the best and much less was it in line with good practices, I finally solved the SEO issue with Angular SSR, I share my repository

https://gitlab.com/mikeag96/angular-ssr

MikeG96 avatar Jun 04 '20 03:06 MikeG96

Hello everyone, after doing more research and seeing that my "solution" mentioned above was not the best and much less was it in line with good practices, I finally solved the SEO issue with Angular SSR, I share my repository

https://gitlab.com/mikeag96/angular-ssr

Please, can you explain your solution? I'm already working with an Angular SSR project and a service to update meta tags, but crawlers don't recognize "in time" the changes.

FabrizioBilleciUNICT avatar Jun 08 '20 17:06 FabrizioBilleciUNICT

Hello everyone, after doing more research and seeing that my "solution" mentioned above was not the best and much less was it in line with good practices, I finally solved the SEO issue with Angular SSR, I share my repository https://gitlab.com/mikeag96/angular-ssr

Please, can you explain your solution? I'm already working with an Angular SSR project and a service to update meta tags, but crawlers don't recognize "in time" the changes.

What are your doubts?

MikeG96 avatar Jun 08 '20 22:06 MikeG96

Hello everyone, after doing more research and seeing that my "solution" mentioned above was not the best and much less was it in line with good practices, I finally solved the SEO issue with Angular SSR, I share my repository

https://gitlab.com/mikeag96/angular-ssr

I tested using your solution and meta tags worked on Facebook and Twitter, but it looks like the standard meta tags didn't work. I tested using https://metatags.io. Did you have this problem too?

evyperez avatar Jun 30 '20 20:06 evyperez

Hello everyone, after doing more research and seeing that my "solution" mentioned above was not the best and much less was it in line with good practices, I finally solved the SEO issue with Angular SSR, I share my repository https://gitlab.com/mikeag96/angular-ssr

I tested using your solution and meta tags worked on Facebook and Twitter, but it looks like the standard meta tags didn't work. I tested using https://metatags.io. Did you have this problem too?

which are your "standard" tags?

MikeG96 avatar Jun 30 '20 21:06 MikeG96

Hello everyone, after doing more research and seeing that my "solution" mentioned above was not the best and much less was it in line with good practices, I finally solved the SEO issue with Angular SSR, I share my repository https://gitlab.com/mikeag96/angular-ssr

Please, can you explain your solution? I'm already working with an Angular SSR project and a service to update meta tags, but crawlers don't recognize "in time" the changes.

What are your doubts?

@https://github.com/MikeG96

So the different in your changes was just { provide: 'NgxRequest', useValue: req, }, { provide: 'NgxResponse', useValue: res, }, in server.ts? and to update the metatags, just use the meta service from Angular. rite?

faizaldong avatar Feb 07 '21 18:02 faizaldong

I just added this { provide: 'NgxRequest', useValue: req, }, { provide: 'NgxResponse', useValue: res, } in server.ts and updated the meta tags with Angular Meta service but it doesn't work. The meta tags can be seen in Element but not in page view source.

faizaldong avatar Feb 07 '21 19:02 faizaldong

app.get('/*', (req, res) => { res.render('index', {req, res}, (err, html) => { if (html) {

    //console.log(html);
    // This is where you get hold of HTML which "is about to be rendered"

    // after some conditional checks make a HTTP call
    let url = 'http://....';
    httpRequest.get(url, (error, response, body) => {
                    if(error) {
                        return console.log(error);
                    }
                    const respBody = JSON.parse(body);
                    if(respBody){
                          html = html.replace(/\$TITLE/g, respBody.title);
                          html = html.replace(/\$DESCRIPTION/g, respBody.description);
                          html = html.replace(/\$OG_META_KEYWORDS/g, respBody.metaKeywords);
                          html = html.replace(/\$OG_META_DESCRIPTION/g, respBody.metaDescription);
                          html = html.replace(/\$OG_DESCRIPTION/g, respBody.ogDescription);
                          html = html.replace(/\$OG_TITLE/g, respBody.ogTitle);
                          html = html.replace(/\$OG_IMAGE/g, respBody.img);
                          html = html.replace(/\$OG_SITE/g, respBody.ogSite);
                    }
                    res.send(html);
        });
 }

} }

HI @bharath-holla ... How to get the route params here? Can you please provide inputs? I need to get the product details and render meta tags based on productId route param.

nikhilbhalwankar avatar Feb 14 '21 18:02 nikhilbhalwankar

app.get('/*', (req, res) => { res.render('index', {req, res}, (err, html) => { if (html) {

    //console.log(html);
    // This is where you get hold of HTML which "is about to be rendered"

    // after some conditional checks make a HTTP call
    let url = 'http://....';
    httpRequest.get(url, (error, response, body) => {
                    if(error) {
                        return console.log(error);
                    }
                    const respBody = JSON.parse(body);
                    if(respBody){
                          html = html.replace(/\$TITLE/g, respBody.title);
                          html = html.replace(/\$DESCRIPTION/g, respBody.description);
                          html = html.replace(/\$OG_META_KEYWORDS/g, respBody.metaKeywords);
                          html = html.replace(/\$OG_META_DESCRIPTION/g, respBody.metaDescription);
                          html = html.replace(/\$OG_DESCRIPTION/g, respBody.ogDescription);
                          html = html.replace(/\$OG_TITLE/g, respBody.ogTitle);
                          html = html.replace(/\$OG_IMAGE/g, respBody.img);
                          html = html.replace(/\$OG_SITE/g, respBody.ogSite);
                    }
                    res.send(html);
        });
 }

} }

HI @bharath-holla ... How to get the route params here? Can you please provide inputs? I need to get the product details and render meta tags based on productId route param.

Try adding

app.get('/custom-path/:param', (req,res) => {
  res.render('index', {req,res}, (err,html)=> {
     if(html){
       ....
     }
});
});

robjean9 avatar Feb 22 '21 17:02 robjean9

I had the same issue and I managed to solve it using resolvers. The problem was when I would view page source after opening a dynamic route I would see meta tags and server side rendering, but facebook didn't see them. So I used a resolver for that route to fetch the data before loading the component and then I took the data and set meta tags inside a constructor of that component. Maybe it would have worked inside ngOnInit as well but I didn't try. Hopefully this will help some of you.

NerminKarapandzic avatar Jun 25 '21 19:06 NerminKarapandzic

I had the same issue and I managed to solve it using resolvers. The problem was when I would view page source after opening a dynamic route I would see meta tags and server side rendering, but facebook didn't see them. So I used a resolver for that route to fetch the data before loading the component and then I took the data and set meta tags inside a constructor of that component. Maybe it would have worked inside ngOnInit as well but I didn't try. Hopefully this will help some of you.

Check my repo: https://gitlab.com/mikeag96/angular-ssr

MikeG96 avatar Jun 25 '21 20:06 MikeG96