myoda999
myoda999

Reputation: 355

Vue application meta tags for social sharing

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

Answers (4)

myoda999
myoda999

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

Radu Diță
Radu Diță

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.

  • I was serving the APP using AWS CloudFront and I had an REST API from where the data was coming from
  • I created a Lambda@Edge that was checking the referrer and then I
  • Started making the REST API calls and just render a blank page with metas.

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

kiddorails
kiddorails

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

priosshrsth
priosshrsth

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

Related Questions