Question

I'm trying to implement the facebook share button in my app, however I can't seem to get it to work on and idk why this is what I have so far.

html(/post/some-random-string)

<div id="fb-root"></div>
<meta property="og:site_name" content="App">
<meta property="og:url" content="/post/{{data.permalink}}">
<meta property="og:title" content="{{data.title}}">
<meta property="og:type" content="blog">
<meta property="og:image" content="https://i1.ytimg.com/vi/tIWPnxEpNQg/maxresdefault.jpg"> 
<meta property="og:description" content="{{data.preview}}">

<body >
<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=580882498674160&version=v2.0";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
   // this facebook share button doesn't appear.
   <div class="fb-share-button" data-href="https://developers.facebook.com/docs/plugins/" data-type="button"></div>
   //so i manually make one.
  <a href="" ng-click='facebookShare();'>Share</a>
 </body>

controller.js

$scope.facebookShare= function(){
   return window.open('http://www.facebook.com/sharer/sharer.php?u='+encodeURIComponent(location.href), 'facebook_share', 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
 }

it works however it didn't read the meta tag i have written above on the html page instead it reads from my index page enter image description here

index page

<!DOCTYPE html>
<html ng-app='app'>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<noscript>
  <meta http-equiv="refresh" content="7">
    <style type="text/css">
      .pagecontainer {display:none;} 
    </style>
    <div class="pure-u-1 text-center">
    <title>Symsal- Oh no ! We need Javascript to work !</title>
    <h3> Please Enable javascript </h3>
    </div>
</noscript>
  <head>
  <title ng-bind='title'></title>
  // some css file 
  </head>
<body>
<div class='puretype'>
<div ng-controller="MasterCtrl">
<div id="layout">
    <!-- Menu toggle -->
    <a href="" id="menuLink" class=" white menu-link">
        <span></span>
    </a>
<div id='menu' class="pure-u-1">
   <div ng-bind-html="userView"></div> 
</div>
</div>
<div class="pure-g-r">
<div id="feed-container" class='pure-u-1 slide'ng-view=''></div>
</div>
</div>
</div>
// some javascript files 
</body>
</html>

facebook debugger enter image description here

Was it helpful?

Solution

What jackypan1989 said is true, you will have to use the absolute url. But one other thing that I'm pretty sure happens is that Facebook won't run your JavaScript code, thus the part

<meta property="og:url" content="/post/{{data.permalink}}">

will never get replaced with

<meta property="og:url" content="/post/the-page-that-was-shared">

This problem that you are having could also prevent Google from crawling your page.

We had the same problem, and we used https://prerender.io to get around it. You can use it on your own server, or use one of their free/paid services.

OTHER TIPS

You already have a body defined around your ng-view. Then your view has its own body. So you are trying to inject a body inside of a body which isn't going to do what you want.

Notice that your controller does not control the HTML element that contains the Meta tags. It only controls code that it contains (a div within the body in your case).

You can add a controller to the HTML tag or you can use $rootScope.

Lots of answers to this here: How to dynamically change header based on AngularJS partial view?

In your controller that handles the ng-view: app.controller('MainControl', function ($rootScope, $scope, Config) { ... $rootScope.canonical = Config.domain; });

I needed to dynamically set a canonical link, but the principal for metas is the same. In your header: <link rel="canonical" ng-href="{{ canonical }}" />

You'll probably want to use ng-bind for a meta tag.

I would add to the previous answers that prerender will solve crawling problems but facebook share is a bit different I think ( feel free to prove me wrong :) ). To avoid annoying {{}} you can define your own meta directive <meta meta-description> and use a template:

app.directive('metaDescription', [ 'metaData', function(metaData){
  return {
    restrict: 'A',
    replace: true,
    template: '<meta name="description" content="{{metaData.pageDesc}}">',
    link: function(scope,element){
      scope.metaData = metaData;


    }
  };
}]);

We are still figuring out SEO/sharing issues with angularJS here but that's what we currently use.

In your codes, you should set up your absolute url on attr 'data-href' of fb-share-button.

For example:

<div class='fb-share-button' data-href='https://yourabsoluteurl.com' data-type='button'>
</div>

I made it work using express. There may be some gaps in this, so if anyone tries it, feel free to fill in the gaps in the comments and I'll update...

I have both express and react running in two different consoles locally. For some reason, I only needed to run node on the express file in prod. Do whatever you need to to get it running. This will forward the request to the react server.

app.get('*', function(req, res) {
    res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

Then I have a route for the pages that I share that looks something like this.

app.get('/details/:itemId', function(req, res) {
    const fileName = path.join(__dirname, 'build', `${req.params.itemId}.html`);
    var fileContents = fs.readFileSync(path.join(__dirname, 'build', 'index.html'), 'utf8');
    fileContents = fileContents.replace("og tags", "new values");
    fs.writeFileSync(fileName, fileContents);
    res.sendFile(fileName);
});

You probably will want to search for the file and serve that up first if it exists so you aren't having problems with multiple clients writing to the same file at the same time in a high volume environment. Or better yet, do it in memory. Remember, order counts in express, so you really need to reverse the order of these two functions in your express file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top