skip to Main Content

I am trying to add og tags that facebook will pickup and from what I have found online, it sounds like angular universal is now merged into angular and should be able to do that by using the platform-browser library.

I started a brand new .net core project with angular support. It created 3 angular components that I was hoping I could test to try and set the og tags – counter.component.ts, fetchdata.component.ts and home.component.ts. Below is an example of what I have in the counter.component.ts constructor.

constructor(private meta: Meta) {
    this.meta.addTags([
        { property: 'og:url', content: 'https://www.oursite.com/counter' },
        { property: 'og:title', content: 'Counter Page' },
        { property: 'og:description', content: 'Counter page description' },
        { property: 'og:image', content: 'https://www.oursite.com/images/angular/counter-page.png' }
    ], false);
}

When I run this and view the source it does in fact add the og tags however they’re rendered inside it’s own html structure within the app tag.

<html>
  <body>
    <app>
      <html>
        <head>
          <meta property="og:title" content="Counter Page">

I found some code for the boot.server.ts file that removes the extra tags leaving just the meta, but because they’re not in the actual head tag facebook’s debugger still doesn’t pick them up.

resolve({
   html: state.renderToString()
       .replace('<html><head>', '')
       .replace('</head><body>', '')
       .replace(/<s*app.*?>/, '')
       .replace('</app></body></html>', '')
});

Everything I’ve read makes it sound like this is how it’s supposed to work and it’s SEO/Social Media friendly. But apparently not. I’m not sure if this is how it’s intended to work or if the .net core template isn’t set up properly?

2

Answers


  1. I don’t think this is accurate: “it sounds like angular universal is now merged into angular and should be able to do that by using the platform-browser library.” They added the MetaService in Angular 4, but that’s not the same thing as adding Angular Universal’s server-side rendering functionality to Angular.

    The Facebook and Twitter crawlers (unlike Google) do not execute any JavaScript, so you have to do this via server-side rendering. I did it by switching to Angular Universal and then using MetaService.

    Note that porting to Angular Universal can be a major change, so do your research before deciding if you want to make the leap.

    Login or Signup to reply.
  2. I have attempted a workarround that i use in my website. Unfortunately facebook doesn’t recognise it very well yet, but i’ll come with an update as soon as i will figure it out.
    Angular 11 Meta tags using NET.5 workarround
    21/1/2021 12:2:47
    Angular 11 Meta tags using NET 5 workarround
    https://softease.ro/news/angular-11-meta-tags-using-net-5-workarround

    How to serve Angular SPA from .NET 5 using the correct meta tags for a specific page.

    1.In your startup declare this middleware. What this will do, is to rewrite the index with the correct meta when the path is one that we know it must have different meta.

      app.Use(async (context, next) =>
               {
                   await next();
                   if (context.Response.StatusCode == 404 &&
                      !Path.HasExtension(context.Request.Path.Value) &&
                      !context.Request.Path.Value.StartsWith("/api/"))
                   {
                       var path = context.Request.Path;
                       if (path.Value.Contains("/view-product/"))
                       {
                           try
                           {
                               var idxPath = Path.Combine(env.ContentRootPath, "wwwroot", "index.html");
                               var index = File.ReadAllText(idxPath);
                               index = ViewProductService.GetMeta(index, path.Value);
                               context.Response.StatusCode = 200;
                               await context.Response.WriteAsync(index);
                               return;
                           }
                           catch
                           {
                           }
                       }
                       else if (path.Value.Contains("/news/"))
                       {
                           try
                           {
                        
    
       var idxPath = Path.Combine(env.ContentRootPath, "wwwroot", "index.html");
                           var index = File.ReadAllText(idxPath);
                           index = NewsService.GetMeta(index, path.Value);
                           context.Response.StatusCode = 200;
                           await context.Response.WriteAsync(index);
                           return;
                       }
                       catch
                       {
                       }
                   }
                   context.Request.Path = "/index.html";
                   await next();
               }
           });
    
    1. Each of your services, must rewrite the index with the correct meta. Let’s take for example NewsService GetMeta:

          var res = (from x in UOW.DbContext.News
                         where (x.Id_News.ToString() == newsId || x.PermaLink == newsId)
                         select new IndexMetaModel()
                         {
                             OgTitle = settings.DisplayName + " " + x.Subject,
                             OgDescription = x.ShortDescription,
                             OgUrl = Globals.AppUrl + "/news/" + x.PermaLink + "/"
                         }).FirstOrDefault();
      

    Read from db and transform into our meta model. Run the model in the IndexMetaUtil.ReplaceTags.

    var resIdx = IndexMetaUtil.ReplaceTags(res, index);
    
    return resIdx;
    

    Bonus:

    Use caching for requests:

      if (NewsDomainService.MetaIndex.ContainsKey(path))
           {`enter code here`
               return NewsDomainService.MetaIndex[path];
           }`enter code here`
    

    IdexMetaUtil:

       public static class IndexMetaUtil
       {
           public static string ReplaceTags(IndexMetaModel meta, string index)
           {
               HtmlDocument doc = new HtmlDocument();
               doc.LoadHtml(index);
               var list = doc.DocumentNode.SelectNodes("//meta");
               bool vidFound = false;
               foreach (var node in list)
               {
                   string property = node.GetAttributeValue("property", "");
                   string value = "";
                   switch (property)
                   {
                       case "og:title":
                           value = meta.OgTitle;
                           node.SetAttributeValue("content", value);
                           break;
                       case "description":
                       case "og:description":
                           var hd = new HtmlDocument();
                           hd.LoadHtml(meta.OgDescription);
                           value = hd.DocumentNode.InnerText;
                           node.SetAttributeValue("content", value);
                           break;
                       case "og:image":
                           if (!vidFound)
                               value = meta.OgImage;
                           node.SetAttributeValue("content", value);
                           break;
                       case "og:url":
                           value = meta.OgUrl;
                           node.SetAttributeValue("content", value);
                           break;
                   }
               }
               return doc.DocumentNode.OuterHtml;
           }
       }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search