{"id":13912580,"url":"https://github.com/vinaygopinath/ngMeta","last_synced_at":"2025-07-18T12:31:53.451Z","repository":{"id":36871587,"uuid":"41178559","full_name":"vinaygopinath/ngMeta","owner":"vinaygopinath","description":"Dynamic meta tags in your AngularJS single page application","archived":false,"fork":false,"pushed_at":"2022-03-23T18:24:37.000Z","size":350,"stargazers_count":153,"open_issues_count":11,"forks_count":42,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-11-18T05:17:47.829Z","etag":null,"topics":["angularjs","crawler","meta-tags","opengraph","seo","ui-router"],"latest_commit_sha":null,"homepage":"http://vinaygopinath.github.io/ngMeta","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vinaygopinath.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-21T21:37:42.000Z","updated_at":"2024-04-15T09:05:45.000Z","dependencies_parsed_at":"2022-09-10T20:00:10.981Z","dependency_job_id":null,"html_url":"https://github.com/vinaygopinath/ngMeta","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinaygopinath%2FngMeta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinaygopinath%2FngMeta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinaygopinath%2FngMeta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinaygopinath%2FngMeta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vinaygopinath","download_url":"https://codeload.github.com/vinaygopinath/ngMeta/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226409771,"owners_count":17620705,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angularjs","crawler","meta-tags","opengraph","seo","ui-router"],"created_at":"2024-08-07T01:01:34.223Z","updated_at":"2024-11-25T22:30:35.916Z","avatar_url":"https://github.com/vinaygopinath.png","language":"JavaScript","funding_links":[],"categories":["crawler"],"sub_categories":[],"readme":"# ngMeta\n\u003e Dynamic meta tags in your AngularJS single page application\n\n[![npm version](https://badge.fury.io/js/ng-meta.svg)](https://badge.fury.io/js/ng-meta) [![Build Status](https://travis-ci.org/vinaygopinath/ngMeta.svg?branch=master)](https://travis-ci.org/vinaygopinath/ngMeta) [![Join the chat at https://gitter.im/ngMeta/Lobby](https://badges.gitter.im/ngMeta/Lobby.svg)](https://gitter.im/ngMeta/Lobby)\n\nThis is an Angular 1.x module. Angular2 module is available as [ng2-meta](https://github.com/vinaygopinath/ng2-meta)\n* [Demo](#demo)\n* [Install](#install)\n* [Getting Started](#getting-started)\n* [Defaults](#defaults)\n* [Dynamic meta tags](#dynamic-meta-tags)\n* [Debugging](#debugging)\n* [Advanced](#advanced)\n  * [Data inheritance in ui-router](#data-inheritance-in-ui-router)\n  * [Using custom data resolved by ui-router](#using-custom-data-resolved-by-ui-router)\n  * [Support for other crawlers](#support-for-other-crawlers)\n* [Websites using ngMeta](#websites-using-ngmeta)\n* [Further reading](#further-reading)\n* [Licence](#mit-licence)\n\n## Demo\n[vinaygopinath.github.io/ngMeta](http://vinaygopinath.github.io/ngMeta)\n\n## Install\n\nvia NPM:\n```shell\nnpm install ng-meta --save\n```\n\nvia Bower:\n```shell\nbower install ngMeta --save\n```\nvia CDN:\n```shell\nhttps://cdnjs.cloudflare.com/ajax/libs/ng-meta/1.0.3/ngMeta.min.js\n```\n\nor download the file from [dist](https://github.com/vinaygopinath/ngMeta/tree/master/dist).\n\n## Getting started\n\n1. Add `ngMeta` as a dependency of your module. ngMeta supports ui-router and ngRoute.\n    ```js\n    angular.module('YourApp',['ngMeta']);\n    ```\n\n2. Add `meta` objects to your routes (ngRoute) or states (ui-router) and specify the meta tags appropriate to each view. Other than `title` and `titleSuffix`, which are reserved properties that affect the title of the page, the tag properties can be named as per your choice.\n    ```js\n    .config(function ($routeProvider, ngMetaProvider) {\n\n      $routeProvider\n      .when('/home', {\n        templateUrl: 'home-template.html',\n        data: {\n          meta: {\n            'title': 'Home page',\n            'description': 'This is the description shown in Google search results'\n          }\n        }\n      })\n      .when('/login', {\n        templateUrl: 'login-template.html',\n        data: {\n          meta: {\n            'title': 'Login page',\n            'titleSuffix': ' | Login to YourSiteName',\n            'description': 'Login to the site'\n          }\n        }\n      });\n      ...\n    });\n    ```\n\n3. **[Optional]** Set the default values of meta tags during Angular's configuration phase. If the `meta` object of a route does not contain a specific tag, the default value is used instead.\n    ```javascript\n    //Add a suffix to all page titles\n    ngMetaProvider.useTitleSuffix(true);\n\n    // On /home, the title would change to\n    // 'Home Page | Best Website on the Internet!'\n    ngMetaProvider.setDefaultTitleSuffix(' | Best Website on the Internet!');\n\n    //Set defaults for arbitrary tags\n    // Default author name\n    ngMetaProvider.setDefaultTag('author', 'John Smith');\n    ```\n\n4. Let `ngMeta` initialize by calling the `init()` function in the app.js `run` block\n    ```js\n    angular.module('YourApp', ['ngRoute', 'ngMeta'])\n    .config(function($routeProvider, ngMetaProvider) {\n      ....\n    })\n    .run(['ngMeta', function(ngMeta) {\n      ngMeta.init();\n    }]);\n    ```\n\n5. Set the meta tags in your HTML file\n    ```html\n    \u003ctitle ng-bind=\"ngMeta.title\"\u003e\u003c/title\u003e\n\n    \u003c!-- Arbitrary tags --\u003e\n    \u003cmeta property=\"og:type\" content=\"{{ngMeta['og:type']}}\" /\u003e\n    \u003cmeta property=\"og:locale\" content=\"{{ngMeta['og:locale']}}\" /\u003e\n    \u003cmeta name=\"author\" content=\"{{ngMeta['author']}}\" /\u003e\n    \u003c!-- OR \u003cmeta name=\"author\" content=\"{{ngMeta.author}}\" /\u003e --\u003e\n    \u003cmeta name=\"description\" content=\"{{ngMeta.description}}\" /\u003e\n    ```\n\n## Defaults\n\nChange app-wide behaviour and set default values to tags using these methods of `ngMetaProvider`. These defaults can be overridden by defining equivalent properties in the route/state `meta` object\n\n```javascript\nangular.module('YourApp', [....,'ngMeta'])\n.config(function(ngMetaProvider) {\n\n\tngMetaProvider.useTitleSuffix(true);\n    ngMetaProvider.setDefaultTitle('Fallback Title');\n    ngMetaProvider.setDefaultTitleSuffix(' | YourSite');\n    ngMetaProvider.setDefaultTag('author', 'John Smith');\n});\n```\n\n| Method | Default | Example |\n| ------ | ------- | ------- |\n| **useTitleSuffix(boolean)**\u003cbr/\u003eToggles the use of a title suffix. When enabled, the title suffix of the route (if available) or the default title suffix is appended to the title of all pages. |  `false` | ngMetaProvider.useTitleSuffix(true);\u003cbr/\u003e |\n| **setDefaultTitle(String)**\u003cbr/\u003eSets the default title for all routes. This serves as a fallback for routes that don't have a `title` property. Use this to customize titles for a few specific routes, letting other routes use the default title. | `undefined` | ngMetaProvider.setDefaultTitle('Spotify');\u003cbr/\u003engMetaProvider.setDefaultTitle('Generic Title'); |\n| **setDefaultTitleSuffix(String)**\u003cbr/\u003eSets the default title suffix for all routes. This serves as a fallback for routes that don't have a `titleSuffix` property. The default title suffix is relevant only when `useTitleSuffix` is set to true. | `undefined` | ngMetaProvider.setDefaultTitleSuffix(' - Site Name');\u003cbr/\u003engMetaProvider.setDefaultTitleSuffix(' - YourSite'); |\n| **setDefaultTag(String, String)**\u003cbr/\u003eSets the default value of any arbitrary tag. This serves as a fallback for routes that don't have a particular tag. | N/A | ngMetaProvider.setDefaultTag('author', 'John Smith');\u003cbr/\u003engMetaProvider.setDefaultTag('ogImgUrl', 'http://example.com/img.png'); |\n\n## Dynamic meta tags\n\nTo change meta tags dynamically (when an item in a list is clicked, for example), inject the `ngMeta` service into your controller and use one of the following methods:\n\n```js\nangular.module('YourApp')\n.controller(function(ngMeta) {\n  //These examples assume useTitleSuffix is enabled,\n  //and default titleSuffix is set to 'Playlist'\n\n  //Custom title and titleSuffix\n  ngMeta.setTitle('Eluvium', ' | Spotify'); //Title = Eluvium | Spotify\n  //default titleSuffix\n  ngMeta.setTitle('Eluvium'); //Title = Eluvium | Playlist\n  //Clear the default titleSuffix\n  ngMeta.setTitle('Eluvium',''); //Title = Eluvium\n\n  ngMeta.setTag('author', 'Matthew Cooper');\n  ngMeta.setTag('image', 'http://placeholder.com/abc.jpg');\n\n  ngMeta.setDefaultTag('author', 'Default author');\n  //Set default tags (non-default tags, like author and image above, are NOT cleared)\n  ngMeta.resetMeta();\n});\n```\n\nNote: Please use `setTitle` to modify the title and/or titleSuffix and `setTag` for all other tags.\n\n| Method | Description | Example |\n| ------ | ------- | ------- |\n| **setTitle(String title, String titleSuffix)** |  Sets the current title based on the given params. When `useTitleSuffix` is enabled and titleSuffix is not provided, it uses the default titleSuffix. | ngMeta.setTitle('Title', ' - TitleSuffix')\u003cbr/\u003e\u003cbr/\u003engMeta.setTitle('Title with default titleSuffix')\u003cbr/\u003e\u003cbr/\u003engMeta.setTitle('Title with no titleSuffix','') |\n| **setTag(String tagName, String value)** | Sets the value of an arbitrary tag, using the default value of the tag when the second param is missing. The value is accessible as {{ngMeta.tagName}} from HTML. Calling setTag with `title` or `titleSuffix` as `tagName` results in an error. Title must be modified using `setTitle` instead.|ngMeta.setTag('author', 'John Smith')\u003cbr/\u003e\u003cbr/\u003engMeta.setTag('ogImage', 'http://url.com/image.png')|\n| **setDefaultTag(String tagName, String value)** | Sets the default value of an arbitrary tag, overwriting previously set default values, but not the value set dynamically (using `setTitle`/`setTag`) or by the route/state. `title` and `titleSuffix` are accepted values.|ngMeta.setDefaultTag('image', 'http://default-image-url.com');\u003cbr/\u003e\u003cbr/\u003engMeta.setDefaultTag('title','Default title');|\n| **resetMeta(void)** | Applies the default meta tags. This is relevant when using ui-router and `disableUpdate: true` (Refer [this comment](https://github.com/vinaygopinath/ngMeta/pull/41#issuecomment-387143832)). Custom tags set dynamically (using `setTag` or `setTitle`) are **not** cleared. |ngMeta.resetMeta();|\n\n\n## Debugging\n* [ng-inspector Chrome extension](https://chrome.google.com/webstore/detail/ng-inspector-for-angularj/aadgmnobpdmgmigaicncghmmoeflnamj) shows the tags set by ngMeta when a state/route is open\n![ng-inspector running on an Angular SPA with ngMeta](http://i.imgur.com/3ltyKC4.png)\n\n* Facebook's [Open Graph Object Debugger](https://developers.facebook.com/tools/debug/og/object/) shows detailed information about your site's meta tags as well as a preview of the snippet shown when your site is shared. **Note that you need to use server-side rendering or prerendering in combination with ngMeta to see your meta tags in the the debugger**\n\n## Advanced\n\n### Data inheritance in ui-router\nIf you wish to take advantage of nested views and data inheritence, then you should specify your `meta` config underneath the `data` property like this:\n\n```javascript\n$stateProvider\n  .state('services', {\n    abstract: true,\n    url: '/services',\n    templateUrl: '/services/base.html',\n    controller: 'servicesCtrl',\n    data: {\n      'meta': {\n        'og:image': 'http://www.yourdomain.com/img/facebookimage.jpg',\n        'author': 'PawSquad'\n      }\n    }\n  })\n  .state('services.vaccinations', {\n    url: '/vaccinations',\n    templateUrl: '/services/vaccinations.html',\n    controller: '',\n    data: {\n      'meta': {\n        'title': 'Pet Vaccinations - All You Need To Know | PawSquad',\n        'og:title': 'All You Need To Know About Pet Vaccinations',\n        'og:description': 'Useful information about Routine Vaccines and Boosters for dogs and cats,   including start vaccines for puppies and kittens.',\n      }\n    }\n  })\n```\n\nFurthermore, you should use the helper function to decorate $stateProvider's `data` function like this\n```javascript\n.config(['ngMetaProvider', function (ngMetaProvider) {\n  $stateProvider.decorator('data', ngMetaProvider.mergeNestedStateData);\n}])\n```\nIn this way the metadata for the `/services/vaccinations` URL would be\n```javascript\n  'meta': {\n    'og:image': 'http://www.yourdomain.com/img/facebookimage.jpg',\n    'author': 'PawSquad',\n    'title': 'Pet Vaccinations - All You Need To Know | PawSquad',\n    'og:title': 'All You Need To Know About Pet Vaccinations',\n    'og:description': 'Useful information about Routine Vaccines and Boosters for dogs and cats, including start vaccines for puppies and kittens.'\n  }\n```\n### Using custom data resolved by ui-router\n\nIf you want to dynamically set your tags using ui-router's [resolve](https://github.com/angular-ui/ui-router/wiki#resolve), this is possible as well:\n```\nresolve: {\n  data: function(..., ngMeta) {\n    //Ex: Load data from HTTP endpoint\n    ....\n    ngMeta.setTitle();\n    ngMeta.setTag('description', '....');\n    ngMeta.setTag('image', '....');\n  }\n},\nmeta: {\n  disableUpdate: true\n}\n```\nThe property `disableUpdate: true` is required because ui-router will execute the resolve function *before* the $stateChangeSuccess event is fired. Setting `disableUpdate: true` will prevent your tags from getting reset by the $stateChangeSuccess event listener.\n\n### Support for other crawlers\n\nWhile Google is capable of rendering Angular sites, other search engines (?) and crawler bots used by social media platforms do not execute Javascript. This affects the site snippets generated by sites like Facebook and Twitter. They may show a snippet like this one:\n\n![Facebook site snippet](http://i.imgur.com/wSNMYNF.png)\n\nYou can use prerendering services to avoid this issue altogether, or update the server config to generate and serve a simplified page with just the open graph meta data needed for the bots to create snippets. Michael Bromley's article, [Enable Rich Sharing In Your AngularJS App](http://www.michaelbromley.co.uk/blog/171/enable-rich-social-sharing-in-your-angularjs-app) has more information on how to do that.\n\n**TL;DR: ngMeta helps the Google crawler render your Angular site and read the meta tags. For other sites like Facebook/Twitter that can't render Javascript, you need to use pre-renderers or server redirects.**\n\n## Websites using ngMeta\n* [acloud.guru](https://acloud.guru) - AWS certification online learning platform\n\nTo list your website here, please make a PR (or [edit README.md on GitHub](https://github.com/vinaygopinath/ngMeta/edit/master/README.md)) and add your URL in this section of README.md in this format\n```\n\"Site URL - Short description\"\n```\n## Further reading\n* [AngularJS \u0026 SEO - finally a piece of cake](https://weluse.de/blog/angularjs-seo-finally-a-piece-of-cake.html)\n* [Fetch as Google - Google Webmaster Tools](https://www.google.com/webmasters/tools/googlebot-fetch)\n* [Deprecating our AJAX crawling scheme - Google Webmaster Blog](https://webmasters.googleblog.com/2015/10/deprecating-our-ajax-crawling-scheme.html)\n* [Open Graph protocol](http://ogp.me/)\n\n## MIT Licence\n*Vinay Gopinath*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinaygopinath%2FngMeta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvinaygopinath%2FngMeta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinaygopinath%2FngMeta/lists"}