我们如何动态添加/更新元标记,以便Facebook / Whatsapp共享对话框选择它们?
我将angular 2应用程序升级为angular 4,以便在我们从API获取组件中的数据后,使用Meta服务动态添加/更新元标记。
到目前为止,在我的组件中,我有
this.metaService.updateTag({ property: 'og:title', content: pageTitle });
this.metaService.updateTag({ property: 'og:url', 'www.domain.com/page' });
this.metaService.updateTag({ property: 'og:image', content: coverUrl, itemprop: 'image' });
this.metaService.updateTag({ property: 'og:image:url', content: coverUrl, itemprop: 'image' });
this.metaService.updateTag({ property: 'og:image:type', content: 'image/png' });
我正在使用updateTag,因为我已经添加了带有默认值的静态标记。当我检查元代码时,此代码会成功更新元标记值。
我知道Facebook / Whatsapp调试工具不执行任何javascript是有道理的,所以它不会在他们的环境中执行。
我正在使用https://developers.facebook.com/tools/debug/
,它总是会选择有意义的默认标记值。
我的问题是,Facebook / Whatsapp动态获取更新的标签值的方法是什么?我正在使用Angular 4并通过API调用加载所有数据,因此在页面加载和执行脚本之前无法获取任何类型的数据。
答案 0 :(得分:12)
你需要提供一个静态的html页面,其中包含og:image og:title和og:html源代码中的开放图形标签,因为facebook,twitter和co只是抓取普通html而不通过javascript渲染它。 Angular通过js动态更新dom,因此抓取工具只获得初始index.html。
有几种方法可以提供包含开放图形的html 标签和解决你的问题:
我猜你已经使用像ngx-meta这样的东西来添加og标签了吗?
我认为服务器端渲染是解决问题的最合适方式。为此,您可以托管节点服务器或使用例如。 AWS Lambda。这样做的缺点是,您的应用必须主动托管,不能再以静态方式提供服务。无论如何,这似乎是最好的方式,因为它也改善了SEO。 Angular Universal是搜索的术语:
您还可以在构建过程中预呈现特定路线,并将角度作为具有多个预渲染index.html文件的静态应用程序提供。如果你只有很少的静态路由,那么这种方法非常好。考虑使用动态部件的更通用路线,这不是解决方案。去服务器端渲染。 angular universal boilerplate也包含一个示例。见prerender.ts
如果您希望避免在构建过程中实现服务器端/预呈现(设置角度通用有时是不好的结构化应用程序的痛苦。)您可以尝试使用预呈现页面的代理服务。看看例如。 prerender.io。
将所有请求重定向到覆盖og:标记的脚本。例如。 Using PHP and .htaccess to overwrite og tags这也适用于现代环境。例如。你可以使用cloudfront / api网关和lambda函数。虽然没有见过这样的例子。
请注意,缓存可能仍会缓存第一次抓取时打开的图形信息。确保您的源代码是最新的,所有缓存,nginxx,cloudfront等反向代理都已清除。
使用Facebook Debugger调试打开的图形缓存并清除facebook opengraph cache
答案 1 :(得分:5)
试试这个(使用fb API:v2.12):
FB.ui({
method: 'share_open_graph',
action_type: 'og.shares',
action_properties: JSON.stringify({
object : {
'og:url': 'url', // your url to share
'og:title': 'title',
'og:site_name':'site_name',
'og:description':'description',
'og:image': 'image Url',//
'og:image:width':'250',//size of image in pixel
'og:image:height':'257'
}
})
}, function(response){
console.log("response is ",response);
});
答案 2 :(得分:3)
如果您使用的是Angular 4,为什么不使用Angular Universal创建页面服务器端 - 这样您就可以在浏览器加载页面之前以编程方式构建HEAD
标记
答案 3 :(得分:0)
在角度6中 动态元标记未反映在index.html
中因此,只有在.htaccess的帮助下才能获得动态元内容。
如果要呈现动态内容,请使用.htaccess。
RewriteCond%{HTTP_USER_AGENT} facebookexternalhit / 1.1 | Twitterbot | Pinterest | linkedinbot | WhatsApp | Viber | SkypeUriPreview | Google。*摘要[NC,OR]
有关更多信息:
https://gist.github.com/thoop/8072354
https://www.winhelp.info/create-browser-whitelist-with-htaccess.html
答案 4 :(得分:0)
截至2018/19年,如果您的主要目标是SEO(或可能更多的“ SMO”-社交媒体优化-因为Googlebot在评估JavaScript方面做得很好,但大多数社交媒体bot却没有),您的SSR解决方案选择可能不应该是Angular Universal,而应该使用无头浏览器。
这应该属于Manuel回答的“代理”类别,但是由于我还没有看到他们在此处发布两个(半个)非常好的解决方案:
这是由Google Chrome团队本身维护的,它只是呈现和返回应用的绝佳端点。
与Rendertron十分相似,但是该工具已经内置了中间件(即,您决定在何处以及如何确定要渲染的请求,而不是哪个请求),并且还具有一些更高级但方便的功能,例如缓存。因此,它确实非常接近“需要零配置”的目标,并且比Rendertron更加容易设置。
再次由Google Chrome小组维护(Rendertron实际使用),Puppeteer为无头Chrome提供了基于节点的高级API。因此,如果以前的项目对您来说有两个难度,您也许可以使用Puppeteer来实现合适的解决方案,但是显然,与仅使用Rendertron或Rendora相比,这将需要更多的工作。
与Angular Universal相比,此解决方案具有巨大的优势,即您的应用程序项目可以完全与使用的SSR工具保持不可知状态(甚至可以使用除Angular之外的任何其他技术)。显然,这不仅为您自己的代码提供了更大的灵活性,还为您的程序包选择提供了更大的灵活性,因为您不必担心它们是否与Angular Universal兼容。 它们的缺点可能是性能开销较小,但是如果您仅针对机器人,则这可能无关紧要。而且,如果您使用Rendora的缓存,则可能甚至不正确,并且实际上可能会提高性能。但是,如果这可以与您不知道使用Angular Universal可以实现的性能提升相提并论。但是请记住,当我们谈论SSR的性能提高时,无论如何,我们总是只谈论首页加载的时间。因此,通常这的重要性不太高,因为您的用户在首次加载后将与您的应用进行更多的交互。如果他们不这样做,那么您主要是匿名用户,他们只检查一个页面然后离开您,那么您可能就不会构建PWA,而是首先构建一个经典网页...
tl; dr只需查看Rendora和Rendertron,它们可能就是您想要的,并且可以非常轻松快捷地使您到达那里。
答案 5 :(得分:0)
在khushali的回答中加上2美分,这对我提供了一个临时解决方案。
在我的托管服务提供商(Dreamhost)上,仅复制/粘贴时[NC,OR]产生了奇怪的结果。在只有一行的RewriteCond上,我不得不将其写为
RewriteCond … googlebot|yandex|…|…|… [NC]
(用每行一个重写RewriteCond也可以,但是在第一行中使用[OR]无效。这可以工作:)
RewriteCond … googlebot [NC]
RewriteCond … yandex [NC,OR]
RewriteCond … WhatsApp [NC,OR]
请注意第一行上似乎缺少的 OR
另一方面,我的第二分是最后一个WhatsApp条目-原来WhatsApp直接从应用程序内部进行抓取(至少今天是在我的Android手机上完成的;)所以我现在就写
RewriteCond %{HTTP_USER_AGENT} googlebot|bingbot|yandex|baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora\ link\ preview|showyoubot|outbrain|pinterest\/0\.|pinterestbot|slackbot|vkShare|W3C_Validator|WhatsApp [NC]
(还有我的完整htaccess
RewriteEngine On
# https://stackoverflow.com/questions/18406156/redirect-all-to-index-php-using-htaccess
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_USER_AGENT} googlebot|bingbot|yandex|baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora\ link\ preview|showyoubot|outbrain|pinterest\/0\.|pinterestbot|slackbot|vkShare|W3C_Validator|WhatsApp [NC]
# RewriteCond %{HTTP_USER_AGENT} facebookexternalhit|googlebot [NC] MUST BE WRITTEN WITHOUT OR
# RewriteCond %{HTTP_USER_AGENT} googlebot [NC]
# RewriteCond %{HTTP_USER_AGENT} facebookexternalhit [NC,OR] 'OR' IS FOR SECOND LINE (AND THIRD AND FOURTH ETC. WON'T WORK ON FIRST LINE)
RewriteRule ^(.*)$ opengraph.php?q=$1 [NC,L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ redir.php?orig_path=$1 [NC,L,QSA]
</IfModule>
答案 6 :(得分:0)
我刚刚为链接创建了一个简单的PHP网站,该网站实现了Open Graph标签,并通过JavaScript将用户重定向到“真实”网站。该脚本执行以下操作:
示例:
<?php
$articleId = $_GET['id'];
$redirectUrl = 'https://yourapp.com/app/tabs/start/article/'.$articleId;
// get the article metadata
$response = file_get_contents('https://api.yourapp.com/articles/'.$articleId);
$response = json_decode($response);
$title = $response->title;
$description = $response->excerpt;
if(property_exists ($response, 'mainImageUrl') ) {
$imageUrl = $response->mainImageUrl;
}
$publishedTime = $response->published;
?>
<html prefix="og: http://ogp.me/ns#">
<head>
<title><?php echo $title ?></title>
<meta name="description" content="<?php echo $description ?>">
<meta property="og:title" content="<?php echo $title ?>">
<meta property="og:description" content="<?php echo $description ?>">
<meta property="og:site_name" content="Your App">
<meta property="og:locale" content="en_US">
<meta property="og:type" content="article">
<meta property="og:url" content="https://yourapp.com/article/<?php echo $articleId ?>">
<?php if(isset($imageUrl)) { echo '<meta property="og:image" content="'.$imageUrl.'">'; } ?>
<meta property="og:image" content="<?php echo $imageUrl ?>">
<meta property="article:published_time" content="<?php echo $publishedTime ?>">
<script>
window.location.href = '<?php echo $redirectUrl ?>';
</script>
</head>
<body>
<a href="<?php echo $redirectUrl ?>">Click here to proceed...</a>
</body>
</html>