Одностраничное приложение не может получить текущий метатег для общего доступа к facebook

Я пытаюсь реализовать кнопку общего доступа к facebook в своем приложении, но я не могу заставить ее работать и idk, почему это то, что у меня есть до сих пор.

HTML (/запись/некоторые-случайная строка)

<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="#" onclick="location.href='https://developers.facebook.com/docs/plugins/'; return false;" 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');
 }

он работает, однако он не читал метатег, который я написал выше на html-странице, вместо этого он читает с моей индексной страницы enter image description here

индексная страница

<!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 enter image description here

Ответ 1

Что сказал jackypan1989, это правда, вы должны использовать абсолютный URL-адрес. Но еще одна вещь, которая, я уверен, случается, заключается в том, что Facebook не будет запускать ваш код JavaScript, таким образом, часть

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

никогда не будет заменен на

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

Эта проблема, с которой вы сталкиваетесь, также может помешать Google обходить вашу страницу.

У нас была та же проблема, и мы использовали https://prerender.io, чтобы обойти это. Вы можете использовать его на своем собственном сервере или использовать одну из своих бесплатных/платных услуг.

Ответ 2

У вас уже есть тело, определенное вокруг вашего ng-view. Тогда ваш взгляд имеет свое тело. Таким образом, вы пытаетесь ввести тело внутри тела, которое не собирается делать то, что вы хотите.

Обратите внимание, что ваш контроллер не контролирует элемент HTML, содержащий метатеги. Он управляет только кодом, который он содержит (div в теле в вашем случае).

Вы можете добавить контроллер в тег HTML или использовать $rootScope.

Много ответов на это здесь: Как динамически изменять заголовок на основе частичного просмотра AngularJS?

В контроллере, который обрабатывает ng-view: app.controller('MainControl', function ($rootScope, $scope, Config) { ... $rootScope.canonical = Config.domain; });

Мне нужно было динамически установить каноническую ссылку, но основной для метасов один и тот же. В вашем заголовке: <link rel="canonical" ng-href="{{ canonical }}" />

Вероятно, вы захотите использовать ng-bind для метатега.

Ответ 3

Я бы добавил к предыдущим ответам, что prerender решит проблемы сканирования, но доля facebook немного отличается, я думаю (не стесняйтесь, чтобы доказать, что я не прав:)). Чтобы избежать раздражающих {{}}, вы можете определить свою собственную мета-директиву <meta meta-description> и использовать шаблон:

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;


    }
  };
}]);

Мы все еще выясняем вопросы SEO/совместного использования с angularJS здесь, но это то, что мы в настоящее время используем.

Ответ 4

В ваших кодах вы должны установить свой абсолютный URL-адрес на attr 'data-href' кнопки fb-share.

Например:

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

Ответ 5

Я сделал это с помощью экспресс. В этом могут быть некоторые пробелы, поэтому, если кто-нибудь попробует это сделать, не стесняйтесь заполнить пробелы в комментариях, и я обновлю...

Я как экспресс, так и реагирую бегаю в двух разных консолях локально. По какой-то причине мне нужно было только запустить узел на экспресс файле в prod. Делайте все, что вам нужно, чтобы запустить его. Это перенаправит запрос на реагирующий сервер.

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

Затем у меня есть маршрут для страниц, которыми я делюсь, который выглядит примерно так.

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);
});

Вы, вероятно, захотите сначала найти файл и обработать его, если он существует, чтобы у вас не возникало проблем с одновременной записью нескольких клиентов в один и тот же файл в среде большого объема. Или еще лучше, сделайте это в памяти. Помните, порядок в экспрессе имеет значение, поэтому вам действительно нужно изменить порядок этих двух функций в вашем файле экспресса.