Change Meta Title and Description using Vue.js

14,737

Solution 1

Since what you want to change is outside the area controlled by Vue, you just use ordinary DOM manipulation. It would be something like

created() {
  fetch('test.json')
    .then(resp => resp.json())
    .then(items => {
      this.items = items;
      const descEl = document.querySelector('head meta[name="description"]');
      const titleEl = document.querySelector('head title');

      descEl.setAttribute('content', items[0]['meta-desc']);
      titleEl.textContent = items[0]['meta-title'];
    })
}

Solution 2

If you are using Vue Router, I believe that cleaner solution is using beforeEach hook:

const routes = [{ path: '/list', component: List, meta: {title:'List'} }]

router.beforeEach((to, from, next) => {
    document.title = to.meta.title
    next()
})

But it allows you set only static titles.

However, if you are looking for some SEO optimizations, Nuxt will probably solve most of your problems

Solution 3

Vue meta is an NPM package for meta-data management: https://vue-meta.nuxtjs.org/

Example of how I use it in a vue page component:

export default {
name: "Contact",
 metaInfo: function() {
   return {
     title: "My page meta title",
     meta: [
     { name: 'description', content:  "My page meta description" }
    ]
  }
 }

If you use Vue Router(that's what I'm doing) you can set Vue meta here so all your page can use it:

import Vue from 'vue'
import Router from 'vue-router'
import VueMeta from 'vue-meta'


Vue.use(Router)
Vue.use(VueMeta)

export default new Router({
mode: 'history',
base: '/',
routes: [
{
  path: '/',
  name: 'Home',
  component: Home
},

Solution 4

If you want to change the title it is easy to change in vuejs.

In router.js file while creating route you can do something like this.

{
    path:"/productdetail",
    name:"productdetail",
    component:ProductDetail,
    meta: {
        title : localStorage.getItem("title"),
    }
    
}

router.beforeEach((toRoute,fromRoute,next) => {
   window.document.title = toRoute.meta.title;
   next();
})

use of localStorage will help you to change title dynamically. unfortunately, meta description is not changing with the same method.

Share:
14,737
Gracie
Author by

Gracie

Updated on June 21, 2022

Comments

  • Gracie
    Gracie almost 2 years

    Is it possible to change anything higher than the body tag in Vue.Js? The contents for both these elements is currently stored in the JSON file that is attached to an element further down the DOM tree.

    I need to try and inject a meta title and description that can be crawled by Google (ie. It injects, then renders before it gets crawled) and understand the issues with accessing the body element and higher up the DOM tree, as the current Vue JSON is injected using the App ID on a DIV lower down.

    I have previously used some jQuery code to address this issue on a Square Space template in some previous work

    jQuery('meta[name=description]').attr('content', 'Enter Meta Description Here');

    PAGE HTML

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <meta name="description" content="{{items[0][0].meta-desc}}">
      <meta name="author" content="">
      <title>{{items[0][0].meta-title}}</title>
      <!-- Bootstrap CSS -->
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
      <!-- Vue.js CDN -->
      <script src="https://unpkg.com/vue"></script>
    </head>
    
    <body>
      <!-- Page List -->
      <div class="container text-center mt-5" id="app">
          <h1 class="display-4">Vue Page Output:</h1>
          <h2>{{items[0][0].page1}}</h2>
      </div>
      <div class="container text-center mt-5">
        <h3>Other Pages</h3>
        <a href="products.html">Products</a>
        <a href="contactus.html">Contact Us</a>
    </div>
      <!-- /.container -->
    
      <script type="text/javascript">
        const app = new Vue({
          el: '#app',
          data: {
            items: []
          },
          created: function () {
            fetch('test.json')
              .then(resp => resp.json())
              .then(items => {
                this.items = items
              })
          }
        });
      </script>
    </body>
    
    </html>
    

    JSON

      [
        [
        {
            "page1": "Company Name",
            "meta-title": "Acme Corp"
            "meta-desc": "Welcome to Acme Corp"
        }
        ],
        [
        {
            "products": "Product List"
        }
        ],
        [
        {
            "contactus": "Contact Us at Acme Corp"
        }
      ]
    

    Here is the code in action, the incoming JSON file comes in a fixed array format with the meta details alongside the body elements. Making this a bit more tricky.

    https://arraydemo.netlify.com/

  • Gracie
    Gracie over 5 years
    Thanks Roy J. That's worked a treat - updated the site now. So this is just vanilla JS but within the Vue method because it is being used on the JSON response right? I'm sure I heard on a tutorial about a certain component way in Vue to work with <head> elements but this will do just fine.
  • Imtiaz
    Imtiaz almost 4 years
    Didn't want to setup anything complicated. This works just fine for me! You have my thanks.
  • moses toh
    moses toh almost 4 years
    @Roy J The title content is change. But if I right-click on the website and select View Page Source, I see the title, description and keywords is don't change
  • Roy J
    Roy J almost 4 years
    @SuccessMan View Page Source effectively downloads the page fresh. Anything that is updated in JavaScript will not be changed there.
  • moses toh
    moses toh almost 4 years
    @Roy J So actually this way is not support SEO
  • Roy J
    Roy J almost 4 years
    @SuccessMan Depends. Google handles JavaScript when crawling sites.
  • moses toh
    moses toh almost 4 years
    @Roy J What do you mean? I said it not support SEO because in View Page Source, the description is not change
  • Roy J
    Roy J almost 4 years
    @SuccessMan I know. But it is wrong to assume that SEO does not allow JavaScript. Google will process the updated description.
  • moses toh
    moses toh almost 4 years
    @Roy J Yes but it doesn't seem optimal
  • Sergiu Mare
    Sergiu Mare almost 3 years
    This is the best approach for Vue ecosystem. Vue-meta offers the possibility to update th head tag if needed. Use computed properties for that.
  • Sergiu Mare
    Sergiu Mare almost 3 years
    Nuxt is using Vue-meta under the hood, so just use Vue-meta in your application. Vue-meta offers a cleaner way to set, remove, create or update the head tag.