Reputation: 355
I have developed a Vue app that has navigation and content on each page. What i need is to setup meta tags for each different page for Twitter and Facebook cards. For that i use vue-meta library and I have come up with the following code:
metaInfo() {
return {
meta: [
{
property: 'og:title',
content: `Card #${this.card_no ? this.card_no : ''}`,
vmid: 'og:title'
},
{
property: 'og:image',
content: `${this.card ? this.card.participantA.image : ''}`,
vmid: 'og:image'
},
{
property: 'og:description',
content: `${this.card ? this.card.description : ''}`,
vmid: 'og:description'
},
{
property: 'twitter:title',
content: `Card #${this.card_no ? this.card_no : ''}`,
vmid: 'twitter:title'
},
{
property: 'twitter:image',
content: `${this.card ? this.card.participantA.image : ''}`,
vmid: 'twitter:image'
},
{
property: 'twitter:description',
content: `${this.card ? this.card.description : ''}`,
vmid: 'twitter:description'
},
{
name: 'twitter:card',
content: `summary_large_image`,
vmid: 'twitter:card'
}
]
}
}
The properties are fetched from an API at the mounted() hook and I can see they are properly added. But the sharing is yet no working, what I believe is they need to be added to the main index.html? But that is impossible in my case since they are dynamic and not always fixed. Is there a way around this? I know that SSR can solve the issue but that is currently not an option since re-writing most of the app using Nuxt is not acceptable at this point of time.
Upvotes: 5
Views: 10672
Reputation: 355
To explain simply what I did is took some advice from all comment above and used a solution in between, shortly I added another middleware in my Express backend that will intercept social bots:
//Social bots intercept
app.use('/info/:id', function (req, res, next) {
let userAgent = req.headers['user-agent'];
if (userAgent.startsWith('facebookexternalhit/1.1') ||
userAgent === 'Facebot' ||
userAgent.startsWith('Twitterbot')) {
...
So if the request is from a bot I just render a view using mustache
res.render('index', injectData)
If the request if not from a bot i just call
next()
And bellow is the code of the index.mustache file I am using:
<!DOCTYPE html>
<html class="no-js" xmlns:fb="http://ogp.me/ns/fb#">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# business: http://ogp.me/ns/business#">
<!-- Facebook metadata -->
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:image" content="{{image}}">
<meta property="og:url" content="{{url}}">
<meta name="twitter:card" content="summary_large_image">
<meta property="og:site_name" content="{{site_name}}">
<meta name="twitter:image:alt" content="{{alt_image}}">
</head>
<body>
<div id="fb-root"></div>
<div id="app"></div>
</body>
</html>
Upvotes: 0
Reputation: 14191
Crawlers don't execute JS, so any solution that uses JS will not work. You'll see the meta's being rendered because your browser executes it.
I had a similar problem and I ended up using the following solution.
This solution is easy to implement if you already use AWS as your hosting.
Note: Google and co don't consider this as cloaking, at least for now.
Upvotes: 0
Reputation: 13014
I faced the similar issues and spent a lot of time in coming with the right solution which involved least amount of code changes in an already tested production-ready code.
You can see my question here - Keeping asset and public path different in vue app for CDN
I finally circled out on Rendertron and it worked like a charm. If you face any issues in it's setup, I can help you further. You can see how rendertron renders a particular page in this sandbox app - https://render-tron.appspot.com/
Upvotes: 0
Reputation: 1158
You can implement SSR without nuxt in any vue app. Unfortunately, I haven't done this myself. But, you can look at this package:
https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer#readme
Upvotes: 1