Vue Server Side Rendering and Twitter Cards - vue.js

Anybody have experience with twitter cards and Vue, dynamically loading meta tags into the components? seems like it needs server side rendering, does anybody know a way to avoid coding all the server side rendering? I am loading the meta tag information from APIs in Vuex and using them within my vue-head meta function:
meta: function() {
return [
//twitter
{ name: "twitter:title", content: this.title, id: "t-title" },
{ name: "twitter:image", content: this.image, id: "t-image" },
{ name: "twitter:description", content: this.excerpt, id: "t-excerpt" },
{
name: "twitter:card",
content: "summary_large_image",
id: "t-card",
},
// Facebook / Open Graph
{ property: "og:title", content: this.title, id: "og-title" },
// with shorthand
{ p: "og:image", c: this.image, id: "og-image" },
];
},

Related

Adding dynamic meta tags fetched from API to nuxtjs static site

I have a static site with Nuxt and content coming in from Strapi. I want to dynamically set the meta tags that are fetched asynchronously.
My site has an index page which passes the fetched data to index-web or index-mobile through props.
let pageMeta: any
const apiBase: string = 'https://strapi.xyz.com'
export default Vue.extend({
components: { Greeting, Showcase, Features, Footer },
props: {
data: Map,
pageMeta,
},
data() {
return {
loading: true,
}
},
metaInfo(): any {
return {
meta: [
{
hid: 'description',
name: 'description',
content: pageMeta.description,
},
{
hid: 'author',
name: 'author',
content: pageMeta.author,
},
],
}
},
})
The prop being passed in a JSON parsed object.
Having done this, the generated site does not have the meta tags added in.
As mentioned, you need to access the property with .this.

How to override global meta tags in a specific template in Nuxt?

I am not sure if this is possible but here it comes.
I have a nuxt.config.js such as (I have changed some information such as content and href attributes for privacy):
head: {
htmlAttrs: {
lang: 'de-DE'
},
title: 'My Title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'My Content.' },
],
link: [
{ rel: 'icon', type: 'image/png', href: '/images/icons/favicon.png' },
{ rel: 'preload', as: 'style', onload: "this.onload=null;this.rel='stylesheet'", href: 'mycss' },
{ rel: 'preload', as: 'style', onload: "this.onload=null;this.rel='stylesheet'", href: 'mycss' },
{ rel: 'dns-prefetch', href: 'https://www.google-analytics.com' }
]
}
As you can see I have two preload link tags which includes onload. I am doing some AMP pages for SEO and AMP gives an error for onload.
The attribute 'onload' may not appear in tag 'link rel=preload
So I want to override those link tags only in my AMP pages. What I have tried is head() function for my AMP pages to override global settings however it didn't override and actually added new links.
export default {
head () {
return {
link: [
// my links
]
}
}
}
I have checked the documentation and looked a few questions here but couldn't find a solution. Is there any way that I can achieve this ?
PS: I want to keep those 2 links in my global because there are lots of pages that uses it.
From nuxt documentation:
To avoid any duplication when used in child components, please give a unique identifier with the hid key to the meta description. This way vue-meta will know that it has to overwrite the default tag.
So try to add an hid attribute to your meta tags to identify them and be able to override them with sub components.
// nuxt.config.js
head: {
link: [
{ hid: 'my-stylesheet', rel: 'preload', as: 'style', href: 'mycss' },
]
}
// page/amp.vue
head: {
link: [
{ hid: 'my-stylesheet', rel: 'preload', as: 'style', href: 'overridedHref' },
]
}
I had as well some issue, with head().
In dev mode I was not seeing any meta data rendered, but when I run nuxtgenereate static (which was my goal anyway) the links were there.
I am not sure, if you wanna go static, but I would try it, to see if it is there or check, what happens if you actually build the app.

Alternate page with proper canonical tag and duplicate URL part errors in Google search console report

I have a static blog site created with Nuxt and hosted on Netlify. For content, I am using markdown files and the new Content module in Nuxt. I used Nuxt and static content, along with vue-meta for SEO purposes, but after a couple months, my coverage report shows multiple errors, and I can't get any pages returned in Google, even when searching on the site name or a specific string of text used on the site.
Here's my setup:
My markdown content is stored in /content/posts
In my blog/index.vue file, this is what I have for my meta tags and data fetching:
<script>
export default {
name: 'Posts',
head() {
return {
title: 'Blog Posts',
meta: [
{
hid: 'description',
name: 'description',
content: 'Example Site blog index'
},
{
hid: 'link',
name: 'link',
content: 'https://example.com/blog'
}
]
}
},
async asyncData({ $content, params }) {
const posts = await $content('posts', params.slug)
.only(['title', 'description', 'publishDate', 'slug'])
.sortBy('publishDate', 'desc')
.fetch()
return {
posts
}
},
};
</script>
In my /blog/_slug/index.vue page, I'm doing almost the same thing.
export default {
name: 'Post',
computed: {
pageConfig() {
return {
identifier: this.post.slug
}
}
},
head() {
return {
title: this.post.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.post.description
},
{
property: "og:site_name",
hid: "og:site_name",
vmid: "og:site_name",
content: "My Site Name"
},
{
property: "og:title",
hid: "og-title",
vmid: "og-title",
content: this.post.title
},
{
property: "og:description",
hid: "og-description",
vmid: "og-description",
content: this.post.description
},
{
property: "og:type",
hid: "og-type",
vmid: "og-type",
content: "article"
},
{
property: "og:url",
hid: "og-url",
vmid: "og-url",
content: 'https://example.com/blog/' + this.post.slug
},
{
hid: "link",
name: "link",
content: 'https://example.com/blog/' + this.post.slug
},
],
link: [
{
rel: 'canonical',
href: 'https://example.com/blog/' + this.post.slug
}
]
}
},
async asyncData({ $content, params }) {
const post = await $content('posts', params.slug).fetch()
return {
post
}
},
}
I'm using this to generate my sitemap in nuxt.config.js
sitemap: {
path: '/sitemap.xml',
hostname: process.env.BASE_URL,
gzip: true,
routes: async () => {
let routes = []
const { $content } = require('#nuxt/content')
let posts = await $content('posts').fetch()
for (const post of posts) {
routes.push(`blog/${post.slug}`)
}
return routes
},
}
and this generates a sitemap at /sitemap.xml with the following structure
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>https://example.com/blog/blog-post-1</loc>
</url>
<url>
<loc>https://example.com/blog/blog-post-2</loc>
</url>
<url>
<loc>https://example.com/blog/blog-post-3</loc>
</url>
</urlset>
I submitted my sitemap to Google.
When I look at my Coverage report in Google Search Console, I have two main problems:
A large number of posts listed under Not Found (404) with a URL of https://example.com/blog/blog/my-blog-post (two /blogs in the URL). I've noticed this happens sometimes when I click on a post right after deploying to Netlify. I've looked around the code, and I can't find where I might be adding an extra /blog in the URL.
An equally large number under Alternate page with proper canonical tag. Before I put the canonical tag in my /_slug/index/vue header, I got errors about missing a canonical tag, and now that I put that in, I get this error instead.
What do I need to do to fix these errors and get my content correctly indexed?

Is it possible to substitute Vue.extend with new Vue?

I am working on a Quasar project and I am having a problem. I need to access from external javascript to the properties and methods of the Vue component.
const vue = Vue.extend({
name: 'PageIndex',
data() {
return {
accessToken:
'myToken',
mapStyle: 'mapbox://styles/mapbox/streets-v11',
coordinates: { lng: -82.42642875898966, lat: 23.11975881338755 },
barbershopsSource: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
title: 'Foo'
},
geometry: {
type: 'Point',
coordinates: [-82.42644475189455, 23.119620627441506]
}
},
{
type: 'Feature',
properties: {
title: 'Bar'
},
geometry: {
type: 'Point',
coordinates: [-82.42193696725194, 23.124402891576594]
}
},
{
type: 'Feature',
properties: {
title: 'Baz'
},
geometry: {
type: 'Point',
coordinates: [-82.43414198682088, 23.115900071933567]
}
}
]
}
};
},
components: {},
methods: {
createMap() {
mapboxgl.accessToken = this.accessToken;
const map = new mapboxgl.Map({
container: 'map',
style: this.mapStyle, // stylesheet location
center: this.coordinates, // starting position [lng, lat]
zoom: 15 // starting zoom
});
const source = this.barbershopsSource;
map.on('load', function() {
console.log('Map loaded');
//I want to have access to the component properties here
});
map.on('click', 'barbershops', function(e) {
console.log('Barbershop clicked:', e.lngLat);
});
}
},
mounted() {
this.createMap();
}
});
export default vue;
I know that access to properties is pretty simple, but the thing is that by default and I don't know why, Quasar uses Vue.extend to create the components. If I substitute
const vue = Vue.extend
by
const vue = new Vue
I can access to properties, but the component view isn't loaded.
Any help would be greatly appreciated
The way it works is, quasar takes App.vue as the entry point and loads the generated compiled javascript. The app is created there.
There is only one app running.
You add functionality to your vue app by extend the app.
You create app once in App.vue and add functionality to it by extending.

Concept for individual menus with json

I'm searching for a database concept for managing a dynamic multilevel menu as JSON Object. Because we have different customers, and the menu is depending on the customer. I'm searching for a database structure to store the following JSON String so that I can edit the structure and create again a json object from the data. How would you realize that? I don't need a complete answer, just an approach.
[
{
name: 'Dashboard',
url: '/dashboard',
writeble: true,
icon: 'icon-speedometer'
},
{
name: 'Menu1',
url: '/menu1',
writeble: true,
icon: 'icon-puzzle',
children: [
{
name: 'Item1.1',
url: '/item/item1.1',
icon: 'icon-puzzle'
subitem: [
{
name: 'Subitem 1',
url: '/item/item1.1',
icon: 'icon-puzzle'
}
},
{
name: 'Item1.2',
url: '/item/item1.2',
icon: 'icon-puzzle'
},
{
name: 'Settings',
url: '/settings',
icon: 'icon-settings'
}
]
}
]
If I understand correctly your question, I would use a NoSql DB where every document is your JSON object and the key is the customer Id.