├── .gitignore
├── README.md
├── book.json
├── docs
├── README.md
├── SUMMARY.md
├── backends.md
├── components
│ ├── autolang.md
│ ├── breadcrumb.md
│ ├── canonical.md
│ ├── description.md
│ ├── image.md
│ ├── index.md
│ ├── lang.md
│ ├── more.md
│ ├── organization.md
│ ├── title.md
│ └── type.md
├── customPolicies.md
├── install.md
├── policies.md
├── predefinedPolicies.md
└── urlChanges.md
├── examples
├── autoLang
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── breadcrumb
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── joinedTitle
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── lang
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
└── title
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── index.js
├── package.json
├── src
├── components
│ ├── autoLang.vue
│ ├── breadcrumbs.vue
│ ├── canonical.vue
│ ├── description.vue
│ ├── head.vue
│ ├── image.vue
│ ├── lang.vue
│ ├── organization.vue
│ ├── title.vue
│ └── type.vue
├── google
│ ├── breadcrumbsDisplayer.vue
│ ├── canonicalDisplayer.vue
│ ├── descriptionDisplayer.vue
│ ├── displayer.vue
│ ├── langDisplayer.vue
│ ├── organizationDisplayer.vue
│ ├── titleDisplayer.vue
│ └── websiteDisplayer.vue
├── main.js
├── middlewares
│ ├── autoLangDisplayer.vue
│ └── displayer.vue
├── mixins
│ ├── displayer.vue
│ ├── ldDisplayer.js
│ ├── optionAccess.js
│ ├── storeAccess.js
│ └── writer.js
├── openGraph
│ ├── descriptionDisplayer.vue
│ ├── displayer.vue
│ ├── imageDisplayer.vue
│ ├── langDisplayer.vue
│ ├── organizationDisplayer.vue
│ ├── titleDisplayer.vue
│ ├── typeDisplayer.vue
│ └── urlDisplayer.vue
└── utils
│ ├── store.js
│ ├── urlChanged.js
│ └── vueStore.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | dist
4 | index.js.map
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 |
15 | # Directory for instrumented libs generated by jscoverage/JSCover
16 | lib-cov
17 |
18 | # Coverage directory used by tools like istanbul
19 | coverage
20 |
21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
22 | .grunt
23 |
24 | # node-waf configuration
25 | .lock-wscript
26 |
27 | # Compiled binary addons (http://nodejs.org/api/addons.html)
28 | build/Release
29 |
30 | # Dependency directory
31 | node_modules
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | _book
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # `vue-seo`
2 |
3 | ## [Full Documentation](http://guillaumeleclerc.github.io/vue-seo/)
4 |
5 | ## Aim
6 |
7 | The aim of this Vue plugin is to help you indexing your Vue powered website using all the greatness of Vue. We also want to give shorthands for common tasks that are usually verbose and reduce the readability of your code.
8 |
9 |
10 | # Showcase
11 |
12 | With this plugin you are able to use this kind of syntax in any component (does not need to be in the head):
13 |
14 | ### Complex title management
15 |
16 | ```html
17 |
21 | ```
22 |
23 |
24 | ### Describe your company
25 | ```html
26 |
31 | ```
32 |
33 | ### Merge policies
34 | ```
35 |
36 |
37 | ```
38 |
39 | with a merge policy for title `VueSEO.policies.join(' - ')` and notifications equal to 3. The title will be:
40 |
41 | `My website - 3 notif.`
42 |
43 | __note__: you can define the two `seo-title` components at different places wherever you want.
44 |
45 | If you want to know more about all the other features just browser the documentation.
46 |
47 | ## Sponsor
48 |
49 | The development of this plugin is made possible by [Papayapods](http://papayapods.com)
50 |
51 |
52 |
--------------------------------------------------------------------------------
/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "gitbook": "2.5.2",
3 | "structure": {
4 | "summary": "docs/SUMMARY.md"
5 | },
6 | "plugins": ["edit-link", "prism", "-highlight", "github", "include-codeblock"],
7 | "pluginsConfig": {
8 | "edit-link": {
9 | "base": "https://github.com/GuillaumeLeclerc/vue-seo/tree/master",
10 | "label": "Edit This Page"
11 | },
12 | "github": {
13 | "url": "https://github.com/GuillaumeLeclerc/vue-seo/"
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # `vue-seo`
2 |
3 | ## Aim
4 |
5 | The aim of this Vue plugin is to help you indexing your Vue powered website using all the greatness of Vue. We also want to give shorthands for common tasks that are usually verbose and reduce the readability of your code.
6 |
7 |
8 | # Showcase
9 |
10 | With this plugin you are able to use this kind of syntax in any component (does not need to be in the head):
11 |
12 | ### Complex title management
13 |
14 | ```html
15 |
19 | ```
20 |
21 |
22 | ### Describe your company
23 | ```html
24 |
29 | ```
30 |
31 | If you want to know more about all the other features just browser the documentation.
32 |
33 | ## Sponsor
34 |
35 | The development of this plugin is made possible by [Papayapods](http://papayapods.com)
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of content
2 |
3 | * [Getting Started](docs/install.md)
4 | * [All Components](docs/components/index.md)
5 | * [Title](docs/components/title.md)
6 | * [Description](docs/components/description.md)
7 | * [Organization](docs/components/organization.md)
8 | * [Breadcrumb](docs/components/breadcrumb.md)
9 | * [Canonical](docs/components/canonical.md)
10 | * [Lang](docs/components/lang.md)
11 | * [AutoLang](docs/components/autolang.md)
12 | * [Image](docs/components/image.md)
13 | * [Type](docs/components/type.md)
14 | * [I want mooore !](docs/components/more.md)
15 | * [Backends](docs/backends.md)
16 | * [Url Changes](docs/urlChanges.md)
17 | * [Policies](docs/policies.md)
18 | * [Default Policies](docs/predefinedPolicies.md)
19 | * [Create your own policy](docs/customPolicies.md)
20 |
--------------------------------------------------------------------------------
/docs/backends.md:
--------------------------------------------------------------------------------
1 | # Backends
2 |
3 | The `seo-*` components enable features on different backends. The following backends are currently supported:
4 |
5 | - __Google__: The components help google understading your data and display it in an enhanced way to your users
6 | - __OpenGraph__: The components helps sharing plateform to understand your data and display them in a good way the following website support this:
7 | - Facebook sharing
8 | - Linkedin sharing
9 | - Google +
10 | - mixi
11 | - Know others? make a pull request :)
12 |
13 |
14 | __IMPORTANT__: To follow the OpenGraph specification you need
15 | - The url (infered automatically by `vue-seo`)
16 | - The type: You absolutely need to have a `` component
17 | - At least one image: set through ``
18 | - A title: set through ``
19 |
20 |
21 | __IMPORTANT__: As of today, Facebook bots does noes render javascript (does not run Vue code). If you want it to be effective you will need to use a prerenderer such as:
22 | - [Prerender-node](https://github.com/prerender/prerender-node)
23 | - [Prerender.io](https://prerender.io)
24 |
25 | Or if you feel risky you can try [`vue-server`](https://github.com/ngsru/vue-server)
26 |
27 | ## Disabling Backends
28 |
29 | If you want to disable a backend you can add the following in the options of VueSEO:
30 |
31 | - __Google__: `google: false`
32 | - __OpenGraph__: `openGraph: false`
33 |
34 | ## Adding Backend
35 |
36 | It's not possible at the moment to add custom backends. If you want this feature (or another) you can make an Issue on the repository.
37 |
--------------------------------------------------------------------------------
/docs/components/autolang.md:
--------------------------------------------------------------------------------
1 | # AutoLang (`seo-auto-lang`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
11 | ```
12 |
13 | ## Props
14 |
15 | - __langs__: The langs the website is available in
16 | - __mode__: How you encode the lang in the url, supported formats:
17 | - `domain`: The lang is an is an ISO-639-1 lang code put as a subdomain. Eg: 'fr.papayapods.com'.
18 | - __default__: This is the default language. It will be ommited in the urls generateds
19 |
20 | ## Impact
21 |
22 | This component will generate automatically `` components based on the current url in all the langs you defined. And automatically updates when the url change.
23 |
24 |
25 | ## Example
26 |
27 | [Try this fiddle](http://jsfiddle.net/gh/get/library/pure/GuillaumeLeclerc/vue-seo/tree/master/examples/autoLang)
28 |
29 | [include](../../examples/autoLang/demo.html)
30 | [include](../../examples/autoLang/demo.js)
31 |
--------------------------------------------------------------------------------
/docs/components/breadcrumb.md:
--------------------------------------------------------------------------------
1 | # Breadcrumb (`seo-breadcrumb`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
7 |
11 | ```
12 |
13 | ## Props
14 |
15 | - __name__: The name to display in the google result for this part of the breadcrumb
16 | - __url__: The url of this part of the breadcrumb
17 | - position: (optional) The position of this fragment in the breadcrumb hierarchy
18 |
19 | ## Impact
20 |
21 | - __Google__: Add readable and clickable breadcrumbs to your search results
22 |
23 | 
24 |
25 | ## Tip
26 |
27 | If you are makin a single page application then you can define a `seo-breadcrumb` in every component. Every time the user (=search bot) switch to anoter page anoter component will change and the breadcrumb will be updated !
28 |
29 | ## Example
30 |
31 | To have the same result as in the previous image you could do this
32 |
33 | [Try this fiddle](http://jsfiddle.net/gh/get/library/pure/GuillaumeLeclerc/vue-seo/tree/master/examples/breadcrumb)
34 |
35 | [include](../../examples/breadcrumb/demo.html)
36 | [include](../../examples/breadcrumb/demo.js)
37 |
38 |
--------------------------------------------------------------------------------
/docs/components/canonical.md:
--------------------------------------------------------------------------------
1 | # Description (`seo-canonical`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
9 | ```
10 |
11 | ## Props
12 |
13 | - __value__ : The canonical link of your page
14 |
15 | ## Impact
16 |
17 | - __Google__: Sets the canonical link of the page
18 |
--------------------------------------------------------------------------------
/docs/components/description.md:
--------------------------------------------------------------------------------
1 | # Description (`seo-description`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
9 | ```
10 |
11 | ## Props
12 |
13 | - __value__ : The description of your page
14 |
15 | ## Impact
16 |
17 | - __Google__: Sets the description of the page (Whats displayed under the title in search resutls)
18 | - __OpenGraph/Facebook search__: Sets the description of your item in the open graph
19 |
--------------------------------------------------------------------------------
/docs/components/image.md:
--------------------------------------------------------------------------------
1 | # Image (`seo-image`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
11 | ```
12 |
13 | ## Props
14 |
15 | - __url__: The url of the image
16 | - __width__: The width of the image
17 | - __height__: The height of the image
18 |
19 | ## Impact
20 |
21 | - __Google__:
22 | - Not (Yet), We are investingating if the Schema.org ImageItem is usefull
23 | - __OpenGraph / Facebook share__:
24 | - Adds one more image describing your open graph item, ie. the picture displayed when you share this item
25 |
26 |
--------------------------------------------------------------------------------
/docs/components/index.md:
--------------------------------------------------------------------------------
1 | # Components
2 |
3 | For the moment these components are available:
4 |
5 | * [Title](title.md)
6 | * [Meta](meta.md)
7 | * [Organization](organization.md)
8 | * [Breadcrumb](breadcrumb.md)
9 | * [HrefLang](hreflang.md)
10 |
11 | But if you think something is missing read [THIS PAGE](more.md)
12 |
--------------------------------------------------------------------------------
/docs/components/lang.md:
--------------------------------------------------------------------------------
1 | # Lang (`seo-lang`)
2 |
3 | This components is here to warn search engines your page is available in other languages
4 |
5 | ## Syntax
6 |
7 | ```html
8 |
9 | ```
10 |
11 | ## Props
12 |
13 | - __code__ : The code for this language
14 | - __url__ : The url of the equivalent page
15 | - __current__: Tells if this is the current displayed language
16 |
17 | ## Impact
18 |
19 | - __Google__:
20 | - Add Hreflang tags, You can read [this](https://en.wikipedia.org/wiki/Hreflang)
21 | - __OpenGraph / Facebook Search__:
22 | - Add locale to your open graph
23 | - Add alternative locales
24 |
25 | ## Example
26 |
27 | [Try this fiddle](http://jsfiddle.net/gh/get/library/pure/GuillaumeLeclerc/vue-seo/tree/master/examples/lang)
28 |
29 | [include](../../examples/lang/demo.html)
30 | [include](../../examples/lang/demo.js)
31 |
32 |
--------------------------------------------------------------------------------
/docs/components/more.md:
--------------------------------------------------------------------------------
1 | # More components
2 |
3 | If you think something is missing and it satisfies the following criteria:
4 |
5 | - Related to search engine optimization
6 | - Is commonly used
7 | - Has (or we suspect it) to have any impact on search engines
8 |
9 | Then create an [issue](https://github.com/GuillaumeLeclerc/vue-seo/issues) and we will try to implement it !
10 |
11 | __important__ : We won't accept every format available on [Schema.org](http://schema.org). It must be supported by at least one search engine.
12 |
--------------------------------------------------------------------------------
/docs/components/organization.md:
--------------------------------------------------------------------------------
1 | # Organization (`seo-organization`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
14 | ```
15 |
16 | ## Props
17 |
18 | - __name__: The name of the organization
19 | - __url__: The url of the website for this organization
20 | - __logo__: The logo of this company
21 | - __contacts__: Array of contacts for this organization, see [THIS](https://developers.google.com/structured-data/customize/contact-points#company_phone_numbers#adding_structured_markup_to_your_site)
22 | - __socialAccounts__: And array of social account page (facebook, youtube, linkedin...)
23 | - __alternateName__: The alternate name of your organization/Website
24 | - __enableWebsite__: [Bool] (advanded) Does this tag describe your website
25 | - __enableOrganization__: [Bool] (advanded) Does this tag describe your organization
26 |
27 | ## Impact
28 |
29 | - __Google__:
30 | - Display a box describing your company on the right pane
31 | - Show your logo on the right pane
32 | - Add social links on the right pane
33 | - Set friendly name for your search results
34 | - Add contact phone on the right pane
35 | - __OpenGraph / Facebook share__:
36 | - Sets the title of your website
37 | - __important__: For the moment if you want to set the image of your facebook search image you have to use ``
38 |
39 | 
40 |
--------------------------------------------------------------------------------
/docs/components/title.md:
--------------------------------------------------------------------------------
1 | # Title (`seo-title`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
9 | ```
10 |
11 | ## Props
12 |
13 | - __value__ : The title of the page
14 |
15 | ## Impact
16 |
17 | - __Google__: Sets the title of the search result
18 | - __Browser__: Sets the title of the window/tab
19 | - __OpenGraph/Facebook search__: Sets the Title of your shared item
20 |
21 | ## Example 1 (Simple)
22 |
23 | [Try this fiddle](http://jsfiddle.net/gh/get/library/pure/GuillaumeLeclerc/vue-seo/tree/master/examples/title)
24 |
25 | [include](../../examples/title/demo.html)
26 | [include](../../examples/title/demo.js)
27 |
28 | ## Example 2 (Complex)
29 |
30 | Does not work for now !
31 | This example make uses of Policies, if you don't know about it yet, read [THIS](../policies.md)
32 |
33 | [Try this fiddle](http://jsfiddle.net/gh/get/library/pure/GuillaumeLeclerc/vue-seo/tree/master/examples/joinedTitle)
34 |
35 | [include](../../examples/joinedTitle/demo.html)
36 | [include](../../examples/joinedTitle/demo.js)
37 |
--------------------------------------------------------------------------------
/docs/components/type.md:
--------------------------------------------------------------------------------
1 | # Type (`seo-type`)
2 |
3 | ## Syntax
4 |
5 | ```html
6 |
9 | ```
10 |
11 | ## Props
12 |
13 | - __value__ : The type of content (The list of available types are available [Here](http://ogp.me/#types)
14 |
15 |
16 | ## Impact
17 |
18 | - __OpenGraph/Facebook search__: Sets the type of object
19 |
--------------------------------------------------------------------------------
/docs/customPolicies.md:
--------------------------------------------------------------------------------
1 | # Custom policy
2 |
3 | In order to write your own policy you need to define a function taking one argument: an array of all definitions for a given attribute and return a string
4 |
5 | ## Example
6 |
7 | ```javascript
8 |
9 | const myStupidPolicy = (possible) => {
10 | return "constant value";
11 | }
12 |
13 | Vue.use(VueSEO, {
14 | policies: {
15 | 'title': myStupidPolicy
16 | }
17 | }
18 | ```
19 |
--------------------------------------------------------------------------------
/docs/install.md:
--------------------------------------------------------------------------------
1 | #Getting started
2 |
3 | ## Install
4 |
5 | ```bash
6 | npm install --save vue-seo
7 | ```
8 |
9 | Or you can the the main javascript file and host it wherever you want (preferably on a CDN).
10 |
11 | __There are no dependency__ (except `vue>=1.0.21` of course)
12 |
13 | ## Load
14 |
15 | If you are using a bundler:
16 |
17 | ```javascript
18 |
19 | import VueSEO from 'vue-seo'
20 | ```
21 |
22 | If you are loading script the "old" way:
23 |
24 | ```html
25 |
26 | ```
27 |
28 | ## Start
29 |
30 | ```javascript
31 | Vue.use(VueSEO, /* options here */);
32 | ```
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/policies.md:
--------------------------------------------------------------------------------
1 | # Policies
2 |
3 | ## Motivation
4 |
5 | What it you define something twice on your page (you could define it in the main component and the other one in a component displayed only if a certain route is matched). For example:
6 |
7 | ```html
8 |
9 |
10 | ```
11 |
12 | What should be the title (ie. displayed on top of the user browser) ?
13 |
14 | Policies are the way to determine the behavior in this kind of situation.
15 |
16 | You can define a property for almost everything defined with `vue-seo` in the option object:
17 |
18 | ```javascript
19 | Vue.use(VueSEO, {
20 | policies: {
21 | 'title': the_policy
22 | }
23 | });
24 | ```
25 |
26 | __Important__: The default policiy if not specified is `VueSEO.policies.last`
27 |
28 | You can either use:
29 | - One of the [predefined policies](predefinedPolicies.md)
30 | - [Make your own policy](customPolicies.md)
31 |
--------------------------------------------------------------------------------
/docs/predefinedPolicies.md:
--------------------------------------------------------------------------------
1 | #Predefined Policies
2 |
3 | The 5 predefined policies are:
4 |
5 | - `VueSEO.policies.last`: With this policy only the last defined value will be considered
6 | - `VueSEO.policies.first`: Only the first defined value will be considered
7 | - `VueSEO.policies.join(glue, reversed=false)`: All values will be considered and joined with `glue` (potenetially reversed)
8 | - `VueSEO.policies.repeat`: The displayer will be repeated for every component you make (eg. there will be 4 title tag if you have 4 seo-title)
9 | - `VueSEO.policies.identity`: The policy does not do anything. That means you need a special backend. It will have to accept an array instead of an object (you should not need it, it should be for internals only)
10 |
11 | ## Example
12 |
13 | [include](../examples/joinedTitle/demo.js)
14 |
--------------------------------------------------------------------------------
/docs/urlChanges.md:
--------------------------------------------------------------------------------
1 | # Url changes
2 |
3 | Some components such as `seo-auto-lang`, needs to know when the url change to update the content. If you use hashes there will no problem. But if you are using html5 history features then there is no event to listen that will tell the component when the url ha changed.
4 |
5 | Since it's considered bad practise to just poll the content of the url bar regulary. We are giving you a way to warn `vue-seo` that the url has changed.
6 |
7 | `VueSEO` is exposing a function you need to call when the url change
8 |
9 | - __VueSEO.urlChangedNotify__
10 |
11 | ## Example (with vue-router)
12 |
13 | ```javascript
14 |
15 | import Vue from 'vue'
16 | import VueSEO from 'vue-seo'
17 | import Router form 'vue-router'
18 |
19 | Vue.use(Router)
20 | Vue.use(VueSEO)
21 |
22 | const router = new Router({
23 | history: true
24 | })
25 |
26 | router.afterEach(function() {
27 | VueSEO.urlChangedNotify()
28 | })
29 | ```
30 |
--------------------------------------------------------------------------------
/examples/autoLang/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Advanced Vue-seo title demo
3 | description: Shows how to use the title component
4 | authors:
5 | - Guillaume Leclerc
6 | normalize_css: no
7 | wrap: l
8 | ...
9 |
--------------------------------------------------------------------------------
/examples/autoLang/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/examples/autoLang/demo.js:
--------------------------------------------------------------------------------
1 | Vue.use(VueSEO, { });
2 |
3 | new Vue({
4 | el: 'body',
5 | })
6 |
7 |
--------------------------------------------------------------------------------
/examples/breadcrumb/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Vue-seo breadcrumbs demo
3 | description: Shows how to use the breadcrumb component
4 | authors:
5 | - Guillaume Leclerc
6 | resources:
7 | - https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.21/vue.js
8 | - https://rawgit.com/GuillaumeLeclerc/vue-seo/master/index.js
9 | normalize_css: no
10 | ...
11 |
--------------------------------------------------------------------------------
/examples/breadcrumb/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/examples/breadcrumb/demo.js:
--------------------------------------------------------------------------------
1 | Vue.use(VueSEO);
2 |
3 | new Vue({
4 | el: 'body',
5 | })
6 |
7 |
--------------------------------------------------------------------------------
/examples/joinedTitle/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Advanced Vue-seo title demo
3 | description: Shows how to use the title component
4 | authors:
5 | - Guillaume Leclerc
6 | normalize_css: no
7 | wrap: l
8 | ...
9 |
--------------------------------------------------------------------------------
/examples/joinedTitle/demo.html:
--------------------------------------------------------------------------------
1 |
12 |
13 |