Showing preview only (8,448K chars total). Download the full file or copy to clipboard to get everything.
Repository: nystudio107/seomatic
Branch: master
Commit: 0876485e9aae
Files: 182
Total size: 8.0 MB
Directory structure:
gitextract_5t9rtuet/
├── .gitignore
├── CHANGELOG.md
├── DOCS.md
├── LICENSE.txt
├── README.md
├── SeomaticPlugin.php
├── composer.json
├── config.php
├── controllers/
│ └── SeomaticController.php
├── elementtypes/
│ └── Seomatic_MetaElementType.php
├── fieldtypes/
│ └── Seomatic_MetaFieldType.php
├── migrations/
│ ├── m151225_000000_seomatic_addHumansField.php
│ ├── m151226_000000_seomatic_addTwitterFacebookFields.php
│ ├── m160101_000000_seomatic_addRobotsFields.php
│ ├── m160111_000000_seomatic_addTitleFields.php
│ ├── m160122_000000_seomatic_addTypeFields.php
│ ├── m160123_000000_seomatic_addOpeningHours.php
│ ├── m160202_000000_seomatic_addSocialHandles.php
│ ├── m160204_000000_seomatic_addGoogleAnalytics.php
│ ├── m160205_000000_seomatic_addResturantMenu.php
│ ├── m160206_000000_seomatic_addGoogleAnalyticsPlugins.php
│ ├── m160206_000000_seomatic_addGoogleAnalyticsSendPageView.php
│ ├── m160209_000000_seomatic_alterDescriptionsColumns.php
│ ├── m160209_000001_seomatic_addRobotsTxt.php
│ ├── m160227_000000_seomatic_addFacebookAppId.php
│ ├── m160416_000000_seomatic_addContactPoints.php
│ ├── m160509_000000_seomatic_addSiteLinksBing.php
│ ├── m160707_000000_seomatic_addGoogleTagManager.php
│ ├── m160715_000000_seomatic_addSeoImageTransforms.php
│ ├── m160723_000000_seomatic_addSeoMainEntityOfPage.php
│ ├── m160724_000000_seomatic_addSeoMainEntityCategory.php
│ ├── m160811_000000_seomatic_addVimeo.php
│ ├── m160904_000000_seomatic_addTwitterFacebookImages.php
│ ├── m161220_000000_seomatic_addPriceRange.php
│ ├── m170212_000000_seomatic_addGoogleAnalyticsAnonymizeIp.php
│ └── m170212_000000_seomatic_addWikipedia.php
├── models/
│ ├── Seomatic_CreatorModel.php
│ ├── Seomatic_IdentityModel.php
│ ├── Seomatic_MetaFieldModel.php
│ ├── Seomatic_MetaModel.php
│ ├── Seomatic_SettingsModel.php
│ ├── Seomatic_SiteMetaModel.php
│ └── Seomatic_SocialModel.php
├── records/
│ ├── Seomatic_MetaRecord.php
│ └── Seomatic_SettingsRecord.php
├── releases.json
├── resources/
│ ├── css/
│ │ ├── bootstrap-tokenfield.css
│ │ ├── css-reset.css
│ │ ├── field.css
│ │ ├── seo-metrics-style.css
│ │ └── style.css
│ └── js/
│ ├── creator.js
│ ├── field.js
│ ├── field_settings.js
│ ├── identity.js
│ ├── main_entity_type_list.js
│ ├── meta.js
│ ├── metalist.js
│ ├── seomatic.js
│ ├── site.js
│ └── type_list.js
├── services/
│ └── SeomaticService.php
├── templates/
│ ├── _error.twig
│ ├── _facebookDisplayPreview.twig
│ ├── _googleAnalytics.twig
│ ├── _googleDisplayPreview.twig
│ ├── _googleTagManager.twig
│ ├── _humans.twig
│ ├── _humansDefault.twig
│ ├── _humansPreview.twig
│ ├── _preview_display_modal.twig
│ ├── _preview_humans_modal.twig
│ ├── _preview_robots_modal.twig
│ ├── _preview_tags_modal.twig
│ ├── _robots.twig
│ ├── _robotsDefault.twig
│ ├── _robotsPreview.twig
│ ├── _seo_meta.twig
│ ├── _seo_metaPreview.twig
│ ├── _seo_metrics.twig
│ ├── _seo_metrics_floater.twig
│ ├── _seomatic_tabs.twig
│ ├── _twitterCardDisplayPreview.twig
│ ├── creator/
│ │ └── _edit.twig
│ ├── field.twig
│ ├── field_settings.twig
│ ├── identity/
│ │ └── _edit.twig
│ ├── index.twig
│ ├── json-ld/
│ │ ├── _json-ld.twig
│ │ └── _json-ld_core.twig
│ ├── meta/
│ │ ├── _edit.twig
│ │ ├── _main.twig
│ │ ├── _sidebar.twig
│ │ └── index.twig
│ ├── seometrics.twig
│ ├── settings.twig
│ ├── site/
│ │ └── _edit.twig
│ ├── social/
│ │ └── _edit.twig
│ └── welcome.twig
├── translations/
│ ├── fr.php
│ └── nl.php
├── twigextensions/
│ └── SeomaticTwigExtension.php
├── variables/
│ └── SeomaticVariable.php
└── vendor/
├── autoload.php
├── composer/
│ ├── ClassLoader.php
│ ├── LICENSE
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_real.php
│ ├── autoload_static.php
│ └── installed.json
├── crodas/
│ └── text-rank/
│ ├── .travis.yml
│ ├── LICENSE
│ ├── README.md
│ ├── composer.json
│ ├── lib/
│ │ └── TextRank/
│ │ ├── Config.php
│ │ ├── DefaultEvents.php
│ │ ├── POS/
│ │ │ └── English/
│ │ │ ├── Tagger.php
│ │ │ ├── generate.php
│ │ │ ├── lexicon.php
│ │ │ └── lexicon.txt
│ │ ├── Stopword/
│ │ │ ├── Stopword.php
│ │ │ ├── czech-stopwords.txt
│ │ │ ├── danish-stopwords.txt
│ │ │ ├── dutch-stopwords.txt
│ │ │ ├── english-stopwords.txt
│ │ │ ├── finnish-stopwords.txt
│ │ │ ├── french-stopwords.txt
│ │ │ ├── generate.php
│ │ │ ├── german-stopwords.txt
│ │ │ ├── hungarian-stopwords.txt
│ │ │ ├── italian-stopwords.txt
│ │ │ ├── norwegian-stopwords.txt
│ │ │ ├── polish-stopwords.txt
│ │ │ ├── portuguese-stopwords.txt
│ │ │ ├── russian-stopwords.txt
│ │ │ ├── spanish-stopwords.txt
│ │ │ ├── swedish-stopwords.txt
│ │ │ └── turkish-stopwords.txt
│ │ ├── Stopword.php
│ │ ├── Summary.php
│ │ ├── SummaryPageRank.php
│ │ ├── TextRank.php
│ │ └── language-profile.php
│ ├── phpunit.xml
│ └── tests/
│ ├── QuickTest.php
│ ├── bootstrap.php
│ └── fixtures/
│ ├── english1.expected
│ ├── english1.summary
│ ├── english1.txt
│ ├── italian.expected
│ ├── italian.summary
│ ├── italian.txt
│ ├── spanish1.expected
│ ├── spanish1.summary
│ └── spanish1.txt
├── davechild/
│ └── textstatistics/
│ ├── .travis.yml
│ ├── LICENSE
│ ├── README.md
│ ├── composer.json
│ ├── phpunit.xml.dist
│ ├── src/
│ │ └── DaveChild/
│ │ └── TextStatistics/
│ │ ├── Maths.php
│ │ ├── Pluralise.php
│ │ ├── Resource.php
│ │ ├── Syllables.php
│ │ ├── Text.php
│ │ ├── TextStatistics.php
│ │ └── resources/
│ │ ├── DaleChallWordList.php
│ │ ├── Homographs.txt
│ │ └── SpacheWordList.php
│ └── tests/
│ ├── TextStatisticsCMULexTest.php
│ ├── TextStatisticsKiplingIfTest.php
│ ├── TextStatisticsMaths.php
│ ├── TextStatisticsMelvilleMobyDickTest.php
│ ├── TextStatisticsPluralise.php
│ └── TextStatisticsTest.php
└── sunra/
└── php-simple-html-dom-parser/
├── README.md
├── Src/
│ └── Sunra/
│ └── PhpSimple/
│ ├── HtmlDomParser.php
│ └── simplehtmldom_1_5/
│ ├── change_log.txt
│ └── simple_html_dom.php
└── composer.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
bower_components
.DS_Store
.idea
================================================
FILE: CHANGELOG.md
================================================
# SEOmatic Changelog
## 1.1.56 - 2017.11.10
### Changed
* Fixed a regression that would cause field sources to not appear in the SEOmatic FieldType
## 1.1.55 - 2017.11.05
### Added
* Added the ability to disable locales via the `config.php` file, for multi-site reasons
* Added paranoid checking for deleted source fields in the FieldType
### Changed
* Fixed an issue with the breadcrumbs potentially overlapping URLs improperly
* Truncate locales to 5 characters, to handle custom locales
## 1.1.54 - 2017.10.10
### Changed
* More intelligent handling of `addTrailingSlashesToUrls`
## 1.1.53 - 2017.10.06
### Changed
* Fixed a regression with certain types of localized sites
## 1.1.52 - 2017.10.02
### Changed
* Fixed breadcrumbs (and other URLs) for certain multi-locale setups
* Fixed an issue with `hreflang='x-default'` with non-localized sites
## 1.1.51 - 2017.09.21
### Added
* Added support for `hreflang="x-default"`
* Added `availabilty` to the default `Offer` Product JSON-LD
### Changed
* Fixed an issue where you could not change the Open Graph or Twitter `title` from a Twig template
* Handle localized elements for breadcrumbs
## 1.1.50 - 2017.08.10
### Added
* Add the ability to override the canonicalUrl from an SEOmatic Meta FieldType
### Changed
* Updated the documentation
## 1.1.49 - 2017.08.02
### Changed
* Don't render "article:tag" if there are no keywords
* Fix issue when passing a string containing the "à" character to _cleanupText()
* Changed `referrer` from `always` to `no-referrer-when-downgrade`
* Fixed an issue where meta vars were not sanitized with a custom template passed via `seomaticTemplatePath`
* Fixed a cosmetic bug where the SEOmatic FieldType settings didn't display the OpenGraph Image Source Changeable properly
* Fixed an issue with template metas on Windows
## 1.1.48 - 2017.06.18
### Changed
* Fixed an issue on old versions of PHP < PHP 5.4 with `http_response_code()`
* Added a safer default `robots.txt` template
## 1.1.47 - 2017.06.08
### Changed
* Fixed an issue with Live Preview and a previous or draft version of an entry
* Fixed a problem where the `dataLayer` wasn't passed down to the Google Tag Manager script
* Commerce products now have the `name` set to the variant + title
## 1.1.46 - 2017.04.08
### Changed
* Force `publisher` to be a `Person` or `Organization` for news articles
* Fixed the AdminCP documentation URL
## 1.1.45 - 2017.03.26
### Changed
* Fixed an issue with `addTrailingSlashesToUrls` and certain PHP configurations
## 1.1.44 - 2017.03.23
### Changed
* Fixed an issue with SEOmetrics and PHP 7.1 that would cause `Error parsing the DOM` errors
* Include our own copy of jQuery for SEOmetrics, rather than depending on the Craft version
* The calls to `file_get_contents` for SEOmetrics are now much more permissive
### Fixed
* If the current request is a 404, set the `canonicalUrl` to an empty string
* If the `canonicalUrl` is set to an empty string, don't render the `<meta rel='canonical'` tag
* Add a trailing / if `addTrailingSlashesToUrls` is set, but only if there's on extension
* Fixed some deprecated meta information in `SeomaticPlugin.php`
## 1.1.43 - 2017.03.03
### Added
* Added Organization to Main Entity of Page
* Improved error logging on internally rendered template errors
### Changed
* The default `robots.txt` template is now smarter about trailing slashes on the `siteUrl`
* Respect `addTrailingSlashesToUrls` when returning fully qualified URLs
* Respect `addTrailingSlashesToUrls` in the URLs returned from `getLocalizedUrls()`
* Dunn & Bradstreet -> Dun & Bradstreet in `DOCS.md`
### Fixed
* Return error messages from internally rendered templates as $htmlText
* Fix for extracting content from a Neo field
## 1.1.42 - 2017.02.12
* [Fixed] Fixed a regression that could cause FieldTypes to not save properly
* [Improved] Moved the lattitude/longitude info down below the address information for on the Site Identity & Site Creator settings
* [Improved] Wrapped all `templates->render()` calls in try/catch blocks to more gracefully handle errors
* [Added] Added an `Anonymize IP` toggle for Google Analytics, for compliance with some local laws
* [Added] Added Wikipedia to the Social Media settings & `sameAs` entity information
## 1.1.41 - 2017.02.10
* [Improved] Broke the changelog out to CHANGELOG.md
* [Fixed] Fixed a bug when saving meta fails
* [Fixed] Fixed an issue with the Charge plugin if you used the Charge element path
* [Fixed] Fixed an issue where re-saving a Section might not re-save the SEOmatic FieldType info
* [Improved] Updated the README.md
## 1.1.40 - 2016.12.20
* [Added] Added support for DigitalProducts and other base purchaseables
* [Fixed] Fixed Commerce deprecation warnings
* [Improved] The FieldType now works with all unknown elementtypes
* [Improved] Works with Eager Loaded elements
* [Improved] Improved the checking on the image fields in case there isn’t anything in there
* [Improved] Always sanitize the array values
* [Improved] Updated the README.md
## 1.1.39 - 2016.09.23
* [Improved] Don't redirect to the welcome page if we're being installed via Console command
* [Improved] Updated the README.md
## 1.1.38 - 2016.09.22
* [Fixed] Fixed an issue with Entry meta and Template Meta would not default Twitter and Facebook images properly
* [Fixed] Fixed an issue where Facebook and Twitter image transforms were not properly applied with Entry and Template meta
* [Fixed] Fixed an issue where elements with certain characters in them could cause invalid Breadcrumb JSON-LD to be generated
* [Improved] The Javascript for the SEOmetrics `Analyze` button now returns false to eliminate the #
* [Improved] Updated the README.md
## 1.1.37 - 2016.09.18
* [Fixed] The Settings template now works with Craft < 2.5
* [Fixed] Fixed a regression that would cause php errors on the settings pages on PHP < 5.5
* [Improved] Updated the README.md
## 1.1.36 - 2016.09.07
* [Fixed] SEOmetrics will now work if `open_basedir` is set
* [Improved] Added html_entity_decode() to the _cleanupText() method
* [Fixed] Fixed an `Integrity constraint violation` MySQL error on certain MySQL versions
* [Improved] Updated the README.md
## 1.1.35 - 2016.09.06
* [Fixed] Fixed a regression that would cause Twitter and Facebook images to not show up
* [Improved] Updated the README.md
## 1.1.34 - 2016.09.05
* [Added] Added the ability to set separate images for Twitter Cards and Facebook OpenGraph images
* [Improved] Do more sanity checking when building the breadcrumbs, so it works if you have not element with the URI `__home__`
* [Improved] We don't swap in the element->title for mainEntityOfPage anymore
* [Added] Added a variable for craft.seomatic.getTemplateMeta()
* [Improved] Protocol-relative URLs are now allowed in the Schema
* [Added] Added `PageWeight` as a metric in SEOmetrics
* [Added] Added the headings to the SEOmetrics display to improve its readability
* [Improved] SEOmetrics now does a better job displaying Top Keywords on pages with very little text
* [Improved] Updated the README.md
## 1.1.32 - 2016.08.25
* [Improved] The SEOmetrics tab in the AdminCP now doesn't start analyzing until you click Analyze
* [Improved] Improved SEOmetric's sitemap.xml detection
* [Improved] Updated DOCS.md to reflect the change from `seomaticProduct` to `seomaticMainEntityOfPage`
* [Improved] Products now have commas stripped from their price, and use a `.` as a decimal point
* [Fixed] Fixed an issue that caused SEOmatic to throw an error in a tokenized entry draft
* [Fixed] Fixed an issue with stale SEOmatic FieldTypes that were added to a section, but then later removed
* [Improved] Updated the README.md
## 1.1.31 - 2016.08.15
* [Added] SEOmetrics now has its own tab, and can evaluate any arbitrary URL you paste into it
* [Added] SEOmatic can now pull images from FocusPoint FieldTypes
* [Added] Added 'Person' as a type for the Main Entity of Page
* [Added] Added Vimeo Handle to Social Media settings
* [Added] Added a 'globalMetaOverride' setting to config.php
* [Added] SEOmetrics checks for HTML validity via the WC3 Validator
* [Added] Added a Score % summary for each SEOmetrics category
* [Added] SEOmetrics now includes Google Pagespeed Insights scores and Google Mobile Usability
* [Added] SEOmetrics checks for SSL encryption via https
* [Improved] Better extraction of 'top keywords on page' in SEOmetrics
* [Improved] SEOmetrics now looks for link rel='publisher'
* [Improved] Refined SEOmetrics a bit, and added more 'Learn More' links
* [Fixed] The mainEntityOfPage is no longer improperly cached if being called by getJsonLd()
* [Improved] Updated the README.md
## 1.1.30 - 2016.08.05
* [Added] Added 'Learn More' link for JSON-LD structured data in SEOmetrics
* [Added] Breadcrumbs get added to WebPage objects, too
* [Improved] SEOmatic now remembers the selected locale in its tabbed settings
* [Improved] Fixed a regression in SEOmetric's keyword in URL checking
* [Improved] Increased HTML SimpleDom's MAX_FILE_SIZE to allow for parsing larger pages (especially with devMode on)
* [Improved] SEOmetrics handles missing robots.txt files more elegantly
* [Improved] SEOmetrics no longer depends on there being an meta description tag
* [Fixed] Fixed an error when using the Share arrow on a draft from Live Preview
* [Fixed] Fixed an issue accessing getJsonLd from an entry that has no URLs or has empty SEOmatic values
* [Fixed] mainEntityOfPage now works for Template Metas
* [Improved] Updated the README.md
## 1.1.29 - 2016.07.31
* [Added] Added the ability to extract seoTitle, seoDescription, and seoKeywords from Neo fields
* [Added] Added the ability to extract seoTitle, seoDescription, and seoKeywords from Preparse fields
* [Added] Added detection of Twitter Card meta tags, OpenGraph meta tags, and JSON-LD structured data in SEOmetrics
* [Added] Added detection robots.txt and sitemaps in SEOmetrics
* [Improved] Breadcrumbs are now generated for every element that matches a URI in the current URL segments
* [Improved] seoTitles, seoDescriptions, and seoKeywords are now truncated on save in SEOmatic Meta FieldTypes when they pull from other fields
* [Improved] Improved the SEOmetrics preview CSS a bit
* [Improved] Updated the README.md
## 1.1.28 - 2016.07.27
* [Added] Added modified_time and published_time to OpenGraph articles when an SEOmatic Meta FieldType is used
* [Improved] Safeguard against 'Undefined index: seoImageTransform'
* [Fixed] Handle non-posted entries
* [Fixed] Fixed an issue with getJsonLD($element)
* [Improved] Updated the README.md
## 1.1.27 - 2016.07.26
* [Fixed] Fixed a regression with Entry Meta cascade
* [Fixed] Fixed an issue with SEOmatic FieldTypes on categories
* [Fixed] Fixed invalid releases.json
* [Improved] We now strip all control characters (including \n and \r) from the JSON-LD arrays
* [Improved] Updated the README.md
## 1.1.26 - 2016.07.25
* [Added] Added Main Entity of Page JSON-LD microdata
* [Added] Added the method getJsonLD($element) to the FieldType model, so you can get the Main Entity of Page JSON-LD for an arbitrary entry (maybe in a craft.entries loop, for instance)
* [Improved] The 'logo' and 'image' in Creator and Identity JSON-LD is now an ImageObject
* [Improved] Added a space after each keyword in SEOmetrics to prevent horizontal scrolling due to frame overflow
* [Fixed] Fixed the locale of the transform fields in the FieldType
* [Fixed] Fix for empty SEO Titles for breadcrumbs
* [Improved] Updated the DOCS.md and wiki docs
* [Improved] Updated the README.md
## 1.1.25 - 2016.07.19
* [Fixed] Fixed an issue with SEO images not rendering properly via the FieldType
* [Fixed] Fixed a typo that would cause Template Metas to not save properly
* [Improved] Added a fallback if `iconv` is not installed for UTF-8 conversion
* [Improved] Explicitly state that the SEO Image must be in JPG, PNG, or GIF format
* [Improved] Updated the README.md
## 1.1.24 - 2016.07.18
* [Added] You can now specify image transforms for your SEO Image, Twitter Image, and Facebook Image for Site Meta, Template Meta, and Entry Metas
* [Added] Added og:image:type, og:image:width, and og:image:height to the OpenGraph meta
* [Added] Added support for Breadcrumbs JSON-LD microdata
* [Improved] the Twig array keys are now quoted in the display preview
* [Improved] Trimmed the fat on some of the settings storage maxLength's
* [Added] Added the ability to control the name of the GTM dataLayer variable
* [Fixed] Added renderGoogleTagManagerScript in config.php
* [Improved] The GTM script tags are now rendered when `devMode` is on, for debugging GTM
* [Improved] Updated the README.md
## 1.1.23 - 2016.07.08
* [Added] Added support for Google Tag Manager (including `dataLayer`)
* [Fixed] Keywords in the SEOmatic Meta FieldType are now tokenized again
* [Fixed] Fixed Javascript error in the FieldType Source popup menu
* [Fixed] Fix Undefined index in getLocalizedUrls
* [Improved] Change seoKeywords -> seoKeywordsUnparsed
* [Added] Add accessors for seoTitleUnparsed, seoDescriptionUnparsed, and seoKeywordsUnparsed
* [Improved] meta keywords and meta description tags only render if they are non-empty
* [Improved] Updated the README.md
## 1.1.22 - 2016.06.27
* [Fixed] Fixed the variable accessor rountines getSocial() and getIdentity()
* [Fixed] Fixed an issue with the 'custom' data not displaying in SEOmatic Meta FieldTypes
* [Improved] Updated the README.md
## 1.1.21 - 2016.06.25
* [Improved] Contents of SEOmatic Meta FieldTypes are now parsed when they are saved, rather than at runtime, which should be faster, and also makes the contents of the fields always accessible. Please re-save your Sections that use SEOmatic FieldTypes as per: [https://github.com/nystudio107/seomatic/wiki/05.-SEO-Entry-Meta](https://github.com/nystudio107/seomatic/wiki/05.-SEO-Entry-Meta)
* [Added] The SEO Title, SEO Description, and SEO Keywords fields in Template Metas can now include tags that output entry properties, such as `{title}` or `{myCustomField}` in them
* [Added] Added a `getLocalizedUrls` Twig filter/function that returns an array of localized URLs for the current request
* [Improved] The SEOmetrics window will now remember its open/closed state while in Live Preview
* [Improved] Some minor tweaks to the SEOmetrics CSS
* [Improved] The current locale is now included in the hreflang for localized sites
* [Improved] The language and country code are now both included in the hreflang for localized sites
* [Improved] The full URL to the current page is now used in the hreflang for localized sites
* [Improved] style and script tags are now stripped out before doing any SEOmetrics on the page
* [Added] Added approximate reading time in the Textual Analysis section of the SEOmetrics
* [Added] You can now control the string prepended to the title tag when devMode is on via config.php
* [Added] Added a French localization for SEOmatic, thanks to @FrancisBou
* [Fixed] We should not properly catch exceptions when there are errors in the variables in the SEOmatic FieldType fields
* [Fixed] Fixed a bug where SEOmetrics might not appear on certain setups that use https
* [Fixed] Fixed Twitter cards, changed `property` to `name`
* [Improved] Updated the README.md
## 1.1.20 - 2016.06.06
* [Added] Added 'Focus Keywords' to the SEOmetrics window, letting you analyze your page content for specific SEO keywords
* [Fixed] Fixed an issue with environmentalVariables in the Site Identity/Entity URL field
* [Improved] Forced CSS style reset on the SEOmetrics skeleton styles
* [Improved] Include port numbers with getFullyQualifiedUrl()
* [Improved] More accurate text to HTML % calculations
* [Improved] Changed the CSS z-index of the SEOmetrics windows to be 9998/9
* [Improved] Updated the README.md
## 1.1.19 - 2016.05.30
* [Fixed] Fixed an issue where the SEOmetrics wouldn't render on certain server setups
* [Added] Added a list of the top keywords on the page to the SEOmetrics
* [Improved] Updated the README.md
## 1.1.18 - 2016.05.30
* [Added] Added "SEOmetrics" displayed during Live Preview that analyizes your page, and generates helpful tips for improving SEO
* [Fixed] SEOmatic will now populate its FieldType with default values on `saveElement()`, which is triggered via import plugings and also via Settings → Edit My Section → hit Save
* [Fixed] Added 'logo' and 'image' to the list of keys that should be always run through getFullyQualifiedUrl()
* [Fixed] Fixed a CSS issue with the AdminCP UI and very large screens
* [Improved] Updated the README.md
## 1.1.17 - 2016.05.09
* [Added] Added support for Google Sitelinks Search Box
* [Added] Added support for Bing site verification
* [Fixed] Fixed a visual display issue with the SEOmatic FieldType Source labels
* [Fixed] Facebook Article tags now use the proper data for author: and publisher:
* [Improved] Updated the README.md
## 1.1.16 - 2016.04.29
* [Added] Added `craft()->seomatic->headlessRenderSiteMeta()` for headless Craft CMS installs
* [Improved] Fixed an issue where Twitter and Facebook properties were double-encoded
* [Fixed] Fixed a visual display issue with tabs and Craft 2.4.x
* [Fixed] Fixed a localization issue with extractTextFromMatrix()
* [Improved] SEOmatic now converts any objects passed into ths seomatic variables to string automatically*
* [Improved] Updated the README.md
## 1.1.15 - 2016.04.25
* [Added] Added a `siteUrlOverride` config setting for when you need to override the `siteUrl`, for instance in a headless ElementAPI server
* [Added] Added breadcrumbs to the AdminCP UI
* [Added] Added the ability to change the display name of the SEOmatic plugin in the AdminCP
* [Improved] Fixed an issue with empty organizationOwnerContactPoints
* [Improved] The array passed into renderJSONLD() is now sanitized before it is rendered
* [Improved] craft.locale is now properly limited to an ISO 639-1 language code in the metadata
* [Improved] Facebook locales now ensure that they have a territory as well as a language, e.g.: fr_FR, not just fr
* [Improved] Updated the README.md
## 1.1.14 - 2016.04.19
* [Added] Added [Organization Contact Points](https://developers.google.com/structured-data/customize/contact-points) that can appear in the Google Knowledge panel in some searches
* [Added] You can control whether Product JSON-LD is rendered via the `renderCommerceProductJSONLD` config variable
* [Added] Added support for arrays as the root JSON-LD type in the JSON-LD generator
* [Improved] SEOmatic now outputs JSON-LD microdata for all of the Craft Commerce Product Variants (previously it was outputting only the default Variant)
* [Improved] Updated the README.md
## 1.1.13 - 2016.04.16
* [Added] If an SEOmatic FieldType is attached to a Craft Commerce Product, in addition to rendering the page SEO Meta, it will also generate [Product JSON-LD microdata](https://developers.google.com/structured-data/rich-snippets/products) that describes the product.
* [Improved] SEOmatic now uses control panel sub-navs if you're running Craft 2.5 or later
* [Improved] Updated the README.md
## 1.1.12 - 2016.04.14
* [Improved] SEOmatic will now populate its FieldType with default values on saveElement(), which is triggered via import plugings and also via Settings → Edit My Section → hit Save
* [Improved] Updated the README.md
## 1.1.11 - 2016.04.08
* [Fixed] Fixed an issue with rendering the humans.tx and robots.txt templates
* [Improved] An HTML comment is added if the Google Analytics script is not included due to LivePreview or devMode being on
* [Improved] Updated the README.md
## 1.1.10 - 2016.03.29
* [Fixed] Fixed API 'deprecation' errors with Craft 2.6.2778 or later
* [Improved] Added more controls for the default title, description, and keywords values in config.php
* [Improved] Updated the README.md
## 1.1.9 - 2016.03.17
* [Fixed] Fixed a typo in the Preview SEO Tags window
* [Fixed] We now handle Twig errors in SEOmatic FieldType fields gracefully
* [Improved] Query strings are now stripped from the canonical URL
* [Improved] All things that should be fully qualified URLs are now fully qualified URLs, even if you specify them via path or relative URL
* [Improved] Updated the README.md
## 1.1.8 - 2016.03.10
* [Improved] In the SEOmatic FieldType, moved default setting to prepValue() so it'll work if the entries are all re-saved via `resaveAllElements`
* [Added] Added getFullyQualifiedUrl() helper as a Twig function/filter and as a variable for Twig templating
* [Improved] Turn things that should be fully qualified URLs into fully qualified URLs, such as the canonicalUrl, seoImage, and anything with `url` as a key
* [Improved] Added seoImage() and seoImageID() to the model so you can get at those values from, say, `entry.seoField.seoImage()`
* [Fixed] canonicalUrl fixes for multilingual sites
* [Fixed] Fixed errant ordinal encoding of the first element in a sequential array
* [Improved] Updated the README.md
## 1.1.7 - 2016.03.04
* [Fixed] Fixed a regression that would cause the Place JSON-LD to render incorrectly
* [Fixed] Fixed a nasty bug that would cause SEOmatic to crash if you used `{title}` or other variables in your SEOmatic Entry Meta fields
* [Improved] Updated the README.md
## 1.1.6 - 2016.03.03
* [Fixed] Fixed a fun recursion bug that would cause meta arrays nested more than 1 deep to not be sanitized & parsed properly
* [Added] Added Composer support for `type: craft-plugin` in `composer.json`
* [Fixed] Removed the `?>` from the `config.php` as per Lindsey's best practices
* [Fixed] The meta variables rendered by `craft.seomatic.renderIdentity()`, `craft.seomatic.renderWebsite()` and `craft.seomatic.renderPlace()` are now taken from the Twig context, so they can be modified before output
* [Fixed] The metas will now be cached as intended (oops), which should increase performance a bit
* [Improved] Updated the README.md
## 1.1.5 - 2016.02.27
* [Added] Added support for OpenGraph `article` types
* [Added] Added support for OpenGraph `fb:app_id` on the Social Media settings
* [Fixed] The canonicalUrl should be set properly to a fully qualified URL now
* [Fixed] The Site Creator will now remember the LocalBusiness and Corporation settings
* [Fixed] The SEOmatic FieldType will preview the canonicalUrl properly now
* [Improved] Updated the README.md
## 1.1.4 - 2016.02.19
* [Added] Set the default Twig escaping strategy for robots.txt and humans.txt to false (so the tag output is not escaped)
* [Fixed] Handle the case where there is no Twitter field
* [Fixed] Handle empty OpeningHours spec correctly, and other OpeningHours fixes
* [Fixed] actionRenderRobots is now publicly accessible (doh!), allowing `robots.txt` to render properly when not logged in
* [Fixed] Fixed a template error on the SEO Site Meta tab on localized sites
* [Improved] Updated the Roadmap section with pending bugs/features
* [Improved] Removed the siteRobotsTxt from the globals display
* [Improved] Updated the README.md
## 1.1.3 - 2016.02.17
* [Fixed] Fixed some typos in SEOmatic & the docs re: `robots.txt`
* [Fixed] The Google Analytics script no longer renders if the Google Analytics Tracking ID field is empty
* [Fixed] Fixed an issue with console errors on the backend with the SEOmatic FieldType
* [Fixed] OpeningHours now only displays for LocalBusiness
* [Added] SEOmatic now processes adding the SEO Site Name to the `og` and `twitter` titles just before rendering, so you can do things like change the `seomaticSiteMeta.siteSeoTitlePlacement` via Twig, and it'll do the right thing
* [Fixed] Fixed a PHP error if the Site Creator is a Person
* [Improved] Updated the README.md
## 1.1.1 - 2016.02.09
* [Added] SEOmatic Meta FieldTypes now work to automatically set meta when attached to `Categories` and also Craft Commerce `Products`
* [Improved] The Google Analytics script tag is not included during Live Preview anymore
* [Added] Added the ability to reference the fields of an SEOmatic FieldType via `entry.mySeomaticField.seoTitle` & `entry.mySeomaticField.seoDescription` & `entry.mySeomaticField.seoKeywords`
* [Added] There is now significantly more space available for the Entity Description and Creator Description
* [Fixed] Fixed an issue with PHP 5.3
* [Added] SEOmatic now handles `robots.txt`; it's configured on the SEO Site Meta tab
* [Improved] Updated the README.md
## 1.1.0 - 2016.02.07
* [Added] Added all of the schema.org Organization types to Identity settings
* [Added] SEOmatic Meta FieldTypes now have settings that let you restrict the Asset Sources available to them
* [Added] SEOmatic Meta FieldTypes now let you set the default Source settings for each field
* [Added] SEOmatic Meta FieldTypes now let you choose if the Source can be changed when editing an entry
* [Added] You can include tags that output entry properties, such as `{title}` or `{myCustomField}` in SEOmatic FieldType fields.
* [Added] Twitter Card and Facebook types can now have null values in the FieldType, and Template meta settings
* [Added] We now include separate Place JSON-LD for Organizations (in addition to being part of the Identity)
* [Added] Added the Opening Hours fields for LocalBusiness, and include the `openingHoursSpecification` in the Site Identity and Place JSON-LD
* [Added] Added support for Google Analytics on the Site Identity tab
* [Added] Added the ability to control whether a `PageView` is automatically sent by Google Analytics
* [Added] Added support for enabling Google Analytics plugins on an a la carte basis
* [Fixed] We now handle numeric Google+ accounts properly
* [Fixed] The Preview buttons display properly on mobile devices for the SEOmatic FieldType now
* [Improved] Added links to WooRank.com for the SEO Title, SEO Description, and SEO Keywords tags that explain best practices for them
* [Added] Added a `config.php` file where you can override some of SEOmatic's default behaviors
* [Added] Added `menu` and `acceptsReservations` fields for FoodEstablishments
* [Improved] Converted all of the `.html` template files over to `.twig`
* [Added] Expanded the JSON-LD parser to support ordinal arrays of associative arrays
* [Fixed] Fixed an issue with the cannonical URL and some localized sites
* [Improved] Updated the README.md
## 1.0.12 - 2016.01.19
* [Improved] Performance improvement by not checking to see if a template exists before matching it
* [Improved] Keyword tags are now saved onblur
* [Improved] The Preview buttons in the SEOmatic FieldType are laid out better now
* [Improved] Updated the README.md
## 1.0.11 - 2016.01.13
* [Added] You can now set Tags fields to be a Source for SEO FieldType Meta fields
* [Added] Added a meta referrer tag to the template (set to 'always')
* [Added] Added a http-equiv='Content-Type' content='text/html; charset=utf-8' meta tag
* [Fixed] If the SEO Title is empty, it no longer appear in the title
* [Fixed] Fixed an issue that would cause the seomatic* variables to not be properly sanitized
* [Improved] Updated the README.md
## 1.0.10 - 2016.01.12
* [Added] You can now set Matrix blocks to be a Source for SEO FieldType Meta fields; it iterates through all text and rich text fields
* [Added] Added a extractTextFromMatrix() Twig filter/function/variable for templating use
* [Improved] The truncateStringOnWord() function does a much better job on comma-delimited keywords now
* [Fixed] Fixed a regression that caused the 'New Template Meta' button to be broken
* [Improved] Updated the README.md
## 1.0.9 - 2016.01.11
* [Added] Added tokenized input fields for the keywords for the Site Meta, Template Meta, and Field Meta
* [Added] You can now specify the position of the SEO Site Title relative to the Title
* [Added] You can now specify the separator character that appears between the SEO Site Title and the Title
* [Fixed] Potentially fixed an issue with iconv when using the extractKeywords() or extractSummary() filters
* [Fixed] Fixed a regression that caused the Template Metas to stop working on the front-end
* [Improved] Updated the README.md
## 1.0.8 - 2016.01.08
* [Improved] The rendering of the Identity and WebSite JSON-LD is now done via a tag in the templates, giving flexibility to people who want to use custom templates
* [Fixed] Fixed an issue with PHP < 5.4
* [Added] If the site is in devMode, `[devMode]` is prepended to the `<title>`
* [Fixed] Fixed an issue if a plugin (like A&M forms) renders a template with Twig code in the template name
* [Improved] Updated the README.md
## 1.0.7 - 2016.01.01
* [Added] Added a 'robots' field globally to the SEO Meta for specifying noindex/nofollow
* [Fixed] Added error handling to the 'Look up Latitude/Longitude' buttons
* [Fixed] Some minor template / logic issues
* [Improved] Updated the README.md
## 1.0.6 - 2015.12.31
* [Added] Added an SEOmatic Meta field type that allows you to attach meta to Entries/Sections
* [Added] The SEOmatic Meta field type can have custom date, or pull from other fields in that Entry, or even extract keywords from other fields
* [Added] You can preview the settings from SEOmatic Meta field types that are attached to entries
* [Fixed] Fixed db error on install on Windows due to trying to set a default for `genericCreatorHumansTxt`
* [Fixed] Facebook Open Graph tags weren't being generated if you had no Facebook Profile ID set, which could cause templating errors
* [Fixed] The `seomatic.twitter.creator` field wasn't set unless `summary_large_image` was chosen, which could cause templating errors
* [Fixed] The seomaticMeta variables were being overzealously encoded as htmlentities
* [Fixed] Fixed an issue where weird characters would appear in truncated strings on certain versions of PHP
* [Improved] All JSON-LD rendered through SEOmatic is now minified if you have the Minify plugin installed
* [Improved] Updated the README.md
## 1.0.5 - 2015.12.28
* [Added] Added 'renderJSONLD' Twig function & filter, and 'craft.seomatic.renderJSONLD()' variable for rendering arbitary JSON-LD schemas
* [Added] SEOmatic now uses 'renderJSONLD' internally to render the Identity and WebSite JSON-LD microdata, rather than templates
* [Added] The 'seomaticIdenity' and 'seomaticCreator' variables are now proper JSON-LD arrays that can be manipulated/added to via Twig
* [Added] Refactored a bunch of internal code to support the new Identity & WebSite formats
* [Added] Rolled all of the SEOmatic calculated variables into the 'seomaticHelper' array
* [Added] Added support for humans.txt authorship accreditation via a tag and template
* [Fixed] Fixed some sticky encoding issues with meta variables
* [Fixed] Cleaned up the code base so we're no longer passing objects around into the templates, just pure arrays, for efficiency's sake
* [Added] Support for Twitter Summary & Summary with Large Image cards
* [Added] The Twitter Card variables are now rendered into the semomaticMeta array, and thus can be independently manipulated
* [Added] The Facebook Open Graph variables are now rendered into the semomaticMeta array, and thus can be independently manipulated
* [Added] Database migrations to support the new features
* [Improved] Updated the README.md
## 1.0.4 - 2015.12.22
* [Added] Added 'copyrightNotice', 'addressString', 'addressHtml', & 'mapUrl' to 'seomaticIdentity'
* [Added] Added 'copyrightNotice', 'addressString', 'addressHtml', & 'mapUrl' to 'seomaticCreator'
* [Added] Added 'hasMap' to the 'location' schema
* [Added] Added a 'Look up Latitude/Longitude' button to the Site Identity & Site Creator settings
* [Fixed] Fixed an issue with the releases.json; the 'Update' button should show up going forward for the plugin
* [Improved] The length of the 'seoSiteName' is now taken into account when truncating the 'seoTitle'
* [Improved] Updated the README.md
## 1.0.3 - 2015.12.21
* [Fixed] Fixed an issue with the TextRank lib not being properly in the git repo, causing it to error when used
* [Fixed] The SEOmatic settings pages now have a SAVE button on them for Craft 2.4
* [Improved] Updated the README.md
## 1.0.2 - 2015.12.20
* [Added] Exposed a few more utility functions via Twig filters & functions
* [Added] The genericOwnerEmail & genericCreatorEmail variables are ordinal-encoded, to obfuscate them
* [Added] Added 'location': 'Place' type to the Identity & Creator schemas, including GeoCoordinates
* [Fixed] Fixed the localization so SEOmatic works if your Admin CP is in a language other than English
* [Improved] Updated the README.md
## 1.0.1 - 2015.12.19
* [Added] If the [Minify](https://github.com/nystudio107/minify) plugin is installed, SEOmatic will minify the SEO Meta tags & JSON-LD
* [Improved] Improved the caching mechanism to span all of the meta
* [Fixed] Fixed a few of small errors
* [Improved] Updated the README.md to better document SEOmatic
## 1.0.0 - 2015.12.18
* Initial release
Brought to you by [nystudio107](http://nystudio107.com)
================================================
FILE: DOCS.md
================================================
# SEOmatic plugin for Craft
A turnkey SEO implementation for Craft CMS that is comprehensive, powerful, and flexible.

## Installation
To install SEOmatic, follow these steps:
1. Download & unzip the file and place the `seomatic` directory into your `craft/plugins` directory
2. -OR- do a `git clone https://github.com/nystudio107/seomatic.git` directly into your `craft/plugins` folder. You can then update it with `git pull`
3. -OR- install with Composer via `composer require nystudio107/seomatic`
4. Install plugin in the Craft Control Panel under Settings > Plugins
5. The plugin folder should be named `seomatic` for Craft to see it. GitHub recently started appending `-master` (the branch name) to the name of the folder for zip file downloads.
SEOmatic works on Craft 2.4.x, Craft 2.5.x, and Craft 2.6.x.
## Overview
### Video overview of SEOmatic:
[](https://www.youtube.com/watch?v=f1149YVEF_0)
SEOmatic allows you to quickly get a website up and running with a robust, comprehensive SEO strategy. It is also implemented in a Craft-y way, in that it is also flexible and customizable. The SEOmetrics feature scans your content for focus keywords, and offers analysis on how to improve your SEO.
It implements [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview) tags, [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph) tags, [Humans.txt](http://humanstxt.org) authorship accreditation, and as well as HTML meta tags.
To better understand how all of this metadata benefits your website, please read: [Promote Your Content with Structured Data Markup](https://developers.google.com/structured-data/)
The general philosophy is that SEO Site Meta can be overridden by SEO Template Meta, which can be overridden by SEO Entry Meta, which can be overridden by dynamic SEO Twig tags.
In this way, the SEO Meta tags on your site cascade, so that they are globally available, but also can be customized in a very granular way.
SEOmatic populates your templates with SEO Meta in the same way that Craft populates your templates with `entry` variables, with a similar level of freedom and flexibility in terms of how you utilize them.
SEOmatic also caches each unique SEO Meta request so that your website performance is minimally impacted by the rich SEO Meta tags provided.
## Rendering your SEO Meta tags
All you need to do in order to output the SEOmatic SEO Meta tags is in the `<head>` tag of your main `layout.twig` (or whatever template all of your other templates `extends`), place this tag:
{% hook 'seomaticRender' %}
That's it. It'll render all of that SEO goodness for you.
SEOmatic uses its own internal template for rendering; but you can provide it with one of your own as well, just use this Twig code instead:
{% set seomaticTemplatePath = 'path/template' %} {% hook 'seomaticRender' %}
...and it'll use your custom template instead.
If the [Minify](https://github.com/nystudio107/minify) plugin is installed, SEOmatic will minify the SEO Meta tags & JSON-LD.
## Configuring SEOmatic
When you first install SEOmatic you'll see a welcome screen, click on the **Get Started** to, well, get started configuring SEOmatic.
All of the SEOmatic settings are fully localizable, so you can have SEO in as many languages as your website supports. If any field is left blank for a setting in a particular locale, it will fall back on the primary locale.
### SEO Site Meta
These SEO Site Meta settings are used to globally define the Meta for the website. When no SEO Template Meta is found for a webpage, these settings are used by default.
They are used in combination with the SEO Template Meta settings to generate [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview), [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph), and as well as HTML meta tags.
If no Template Meta exists for a template, the SEO Site Meta is used.
If any fields are left blank in a Template Meta, those fields are pulled from the SEO Site Meta.
You can also dynamically change any of these SEO Meta fields in your Twig templates, and they will appear in the rendered SEO Meta.
* **Site SEO Name** - This field is used wherever the name of the site is referenced, both at the trailing end of the `<title>` tag, and in other meta tags on the site. It is initially set to your Craft `{{ siteName }}`.
* **Site SEO Title** - This should be between 10 and 70 characters (spaces included). Make sure your title tag is explicit and contains your most important keywords. Be sure that each page has a unique title tag.
* **Site SEO Name Placement** - Where the Site SEO Name is placed relative to the Title in the `<title>` tag
* **Site SEO Name Separator** - The character that should be used to separate the Site SEO Name and Title in the `<title>` tag
* **Site SEO Description** - This should be between 70 and 160 characters (spaces included). Meta descriptions allow you to influence how your web pages are described and displayed in search results. Ensure that all of your web pages have a unique meta description that is explicit and contains your most important keywords.
* **Site SEO Keywords** - Google ignores this tag; though other search engines do look at it. Utilize it carefully, as improper or spammy use most likely will hurt you, or even have your site marked as spam. Avoid overstuffing the keywords and do not include keywords that are not related to the specific page you place them on.
* **Site SEO Image** - This is the image that will be used for display as the global website brand, as well as on Twitter Cards and Facebook OpenGraph that link to the website, if they are not specified. The image must be in JPG, PNG, or GIF format.
* **Site SEO Image Transform** - The image transform to apply to the Site SEO Image.
* **Site Twitter Card Type** - With Twitter Cards, you can attach rich photos and information to Tweets that drive traffic to your website. Users who Tweet links to your content will have a “Card” added to the Tweet that’s visible to all of their followers.
* **Site Twitter Card Image** - This is the image that will be used for display on Twitter Cards in tweets that link to the website. If no image is specified here, the Site SEO Image will be used for Twitter Cards instead. The image must be in JPG, PNG, or GIF format.
* **Site Twitter Card Image Transform** - The image transform to apply to the Twitter SEO Image. Twitter recommends: 120 x 120 pixels minimum size, 1:1 aspect ratio, 1mb max size for Summary Card images, and 280x150 pixels minimum size, 1.86:1 aspect ratio, 1mb max size for Summary Card with Large Image images.
* **Site Facebook OpenGraph Type** - Adding OpenGraph tags to your website influences the performance of your links on social media by allowing you to control what appears when a user posts a link to your content on Facebook.
* **Site Facebook OpenGraph Image** - This is the image that will be used for display on Facebook posts that link to the website. If no image is specified here, the Site SEO Image will be used for Facebook posts instead. The image must be in JPG, PNG, or GIF format.
* **Site Facebook OpenGraph Image Transform** - The image transform to apply to the Facebook SEO Image. Facebook recommends: 1200 x 630 pixels minimum size, 1.9:1 aspect ratio, 8mb max size.
* **Site Robots** - The [robots meta tag](https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag?hl=en) lets you utilize a granular, page-specific approach to controlling how an individual page should be indexed and served to users in search results. Setting it to a blank value means 'no change'.
#### SiteLinks Search Box
With [Google Sitelinks search box](https://developers.google.com/structured-data/slsb-overview), from search results. Search users sometimes use navigational queries, typing in the brand name or URL of a known site or app, only to do a more detailed search once they reach their destination.
* **Search Targets** - This property specifies a search URL pattern for sending queries to your site's search engine. It must include a string enclosed in curly braces that is a placeholder for the user's search query (e.g., `{search_term_string}`). The string inside the curly braces must also appear in the name attribute of the query-input property.
* **Search Query Input** - The value for the name attribute of query-input must match the string enclosed inside curly braces in the target property of potentialAction, e.g.: `searchtermstring`
#### robots.txt
* **robots.txt Template** - A `robots.txt` file is a file at the root of your site that indicates those parts of your site you don’t want accessed by search engine crawlers. The file uses the [Robots Exclusion Standard](http://en.wikipedia.org/wiki/Robots_exclusion_standard#About_the_standard), which is a protocol with a small set of commands that can be used to indicate access to your site by section and by specific kinds of web crawlers (such as mobile crawlers vs desktop crawlers).
SEOmatic automatically handles requests for `/robots.txt`. For this to work, make sure that you do not have an actual `robots.txt` file in your `public/` folder (because that will take precedence).
If you are running Nginx, make sure that you don't have a line like:
location = /robots.txt { access_log off; log_not_found off; }
...in your config file. A directive like this will prevent SEOmatic from being able to service the request for `/robots.txt`. If you do have a line like this in your config file, just comment it out, and restart Nginx with `sudo nginx -s reload`.
The **Preview Robots.txt** button lets you preview what your rendered robots.txt file will look like.
You can use any Craft `environmentVariables` in these fields in addition to static text, e.g.:
This is my {baseUrl}
### Site Identity
These Site Identity settings are used to globally define the identity and ownership of the website.
They are used in combination with the SEO Template Meta settings to generate [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview), [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph), and as well as HTML meta tags.
The Site Owner type determines the JSON-LD schema that will be used to identity the website to search engines.
Leave any fields blank that aren't applicable or which you do not want as part of the SEO schema.
#### Site Ownership
* **Google Site Verification** - For the `<meta name='google-site-verification'>` tag. Only enter the code in the `content=''`, not the entire tag. [Here's how to get it.](https://www.google.com/webmasters/verification/).
* **Bing Site Verification** - For the `<meta name='msvalidate.01'>` tag. Only enter the code in the `content=''`, not the entire tag. [Here's how to get it.](https://www.bing.com/webmaster/help/how-to-verify-ownership-of-your-site-afcfefc6).
* **Google Tag Manager ID** - If you enter your Google Tag Manager ID here, the Google Tag Manager script tags will be included in your `<head>` (the script is not included during Live Preview). Only enter the ID, e.g.: `GTM-XXXXXX`, not the entire script code. [Here's how to get it.](https://support.google.com/tagmanager/answer/6102821?hl=en)
* **Google Analytics Tracking ID** - If you enter your Google Analytics Tracking ID here, the Google Analytics script tags will be included in your `<head>` (the script is not included if `devMode` is on or during Live Preview). Only enter the ID, e.g.: `UA-XXXXXX-XX`, not the entire script code. [Here's how to get it.](https://support.google.com/analytics/answer/1032385?hl=en)
* **Automatically send Google Analytics PageView** - Controls whether the Google Analytics script automatically sends a PageView to Google Analytics when your pages are loaded
* **Google Analytics Plugins** - Select which Google Analytics plugins to enable. [Learn More](https://developers.google.com/analytics/devguides/collection/analyticsjs/)
* **Site Owner Entity Type** - The type of entity that owns this website. Choose as general or specific of a type as you like. Any entity sub-type left blank is ignored.
More fields will also appear depending on the selected **Site Owner Entity Type**. For instance, any `LocalBusiness` sub-type will receive a field for **Opening Hours**, so that the hours that the business is open will be rendered in the Identity and Place JSON-LD microdata.
##### Google Tag Manager
Note that the Google Tag Manager implementation supports the `dataLayer` property. You can set it like any other Twig array:
{% set dataLayer = {
'pageCategory': entry.category,
'visitorType': 'high-value'
} %}
You can set the `dataLayer` Twig variable either in your templates that extend your `layout.twig` or in your `layout.twig` itself. The usual rules on Twig variable scoping apply, you just need to set the `dataLayer` array before the `{% hook seomaticRender %}` is called. [Learn More](https://developers.google.com/tag-manager/devguide)
There is also a `gtmDataLayerVariableName` variable in `config.php` which allows you to control the name of the Javascript `dataLayer` variable.
#### General Info
* **Entity Name** - The name of the entity that owns the website
* **Alternate Entity Name** - An alternate or nickname for the entity that owns the website
* **Entity Description** - A description of the entity that owns the website
* **Entity URL** - A URL for the entity that owns the website
* **Entity Brand** - An image or logo that represents the entity that owns the website. The image must be in JPG, PNG, or GIF format.
* **Entity Telephone** - The primary contact telephone number for the entity that owns the website
* **Entity Email** - The primary contact email address for the entity that owns the website
#### Location Info
* **Entity Latitude** - The latitude of the location of the entity that owns the website, e.g.: -120.5436367
* **Entity Longitude** - The longitude of the location of the entity that owns the website, e.g.: 80.6033588
* **Entity Street Address** - The street address of the entity that owns the website, e.g.: 123 Main Street
* **Entity Locality** - The locality of the entity that owns the website, e.g.: Portchester
* **Entity Region** - The region of the entity that owns the website, e.g.: New York or NY
* **Entity Postal Code** - The postal code of the entity that owns the website, e.g.: 14580
* **Entity Country** - The country in which the entity that owns the website is located, e.g.: US
#### Organization Info
* **Organization DUNS Number** - The DUNS (Dun & Bradstreet) number of the organization/company/restaurant that owns the website
* **Organization Founder** - The name of the founder of the organization/company/restaurant
* **Organization Founding Date** - The date the organization/company/restaurant was founded
* **Organization Founding Location** - The location where the organization/company/restaurant was founded
* **Organization Contact Points** - Use [organization contact points](https://developers.google.com/structured-data/customize/contact-points) to add your organizations's contact information to the Google Knowledge panel in some searches. The Telephone Number must be an internationalized version of the phone number, starting with the '+' symbol and country code (+1 in the US and Canada). e.g.: +1-800-555-1212 or +44-2078225951
#### Local Business Info
* **Opening Hours** - The opening hours for this local business. If the business is closed on a given day, just leave the hours for that day blank.
#### Corporation Info
* **Corporation Ticker Symbol** - The exchange ticker symbol of the corporation
#### Food Establishment Info
* **Food Establishment Cuisine** - The primary type of cuisine that the food establishment serves
* **Food Establishment Menu URL** - URL to the food establishment's menu
* **Food Establishment Reservations URL** - URL to the food establishment's reservations page
#### Person Info
* **Person Gender** - The gender of the person
* **Person Birth Place** - The place where the person was born
You can use any Craft `environmentVariables` in these fields in addition to static text, e.g.:
This is my {baseUrl}
### Social Media
These Social Media settings are used to globally define the social media accounts associated with your website.
They are used in combination with the SEO Template Meta settings to generate [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview), [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph), and as well as HTML meta tags.
None of these fields are mandatory; if you don't have a given social media account, just leave it blank.
* **Twitter Handle** - Your Twitter Handle, without the preceding @
* **Facebook Handle** - Your Facebook company/fan page handle (the part after `https://www.Facebook.com/`
* **Facebook Profile ID** - Your Facebook Profile/Page ID. Click on the 'About' tab on your Facebook company/fan page, click on 'Page Info', then scroll to the bottom to find your 'Facebook Page ID'
* **Facebook App ID** - Your Facebook App ID. Providing a Facebook Application ID for use with the Social Media Sharing feature is recommended, but optional. [Learn More](https://developers.facebook.com/docs/apps/register)
* **LinkedIn Handle** - Your LinkedIn page handle (the part after `https://www.linkedin.com/in/` or `https://www.linkedin.com/company/`)
* **Google+ Handle** - Your Google+ page handle, without the preceding +. If you have a numeric Google+ account still, just enter that.
* **YouTube User Handle** - Your YouTube handle (the part after `https://www.youtube.com/user/`)
* **YouTube Channel Handle** - Your YouTube handle (the part after `https://www.youtube.com/c/`)
* **Instagram Handle** - Your Instagram handle
* **Pinterest Handle** - Your Pinterest page handle (the part after `https://www.pinterest.com/`)
* **Github Handle** - Your Github page handle (the part after `https://github.com/`)
You must have a **Twitter Handle** for SEOmatic to generate Twitter Card tags for you. Similarly, you should have a **Facebook Profile ID** for the Facebook Open Graph tags, but it's not required.
You can use any Craft `environmentVariables` in these fields in addition to static text, e.g.:
This is my {baseUrl}
### Site Creator
These Site Creator settings are used to globally define & attribute the creator of the website. The creator is the company/individual that developed the website.
They are used in combination with the SEO Template Meta settings to generate [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview), [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph), and as well as HTML meta tags.
The Site Creator information is referenced in the Identity JSON-LD schema that is used to identity the website to search engines.
Leave any fields blank that aren't applicable or which you do not want as part of the SEO schema.
#### Site Creator
* **Site Creator Entity Type** - The type of entity that created this website.
#### General Info
* **Entity Name** - The name of the entity that created the website
* **Alternate Entity Name** - An alternate or nickname for the entity that created the website
* **Entity Description** - A description of the entity that created the website
* **Entity URL** - A URL for the entity that created the website
* **Entity Brand** - An image or logo that represents the entity that created the website. The image must be in JPG, PNG, or GIF format.
* **Entity Telephone** - The primary contact telephone number for the entity that created the website
* **Entity Email** - The primary contact email address for the entity that created the website
#### Location Info
* **Entity Latitude** - The latitude of the location of the entity that created the website, e.g.: -120.5436367
* **Entity Longitude** - The longitude of the location of the entity that created the website, e.g.: 80.6033588
* **Entity Street Address** - The street address of the entity that created the website, e.g.: 575 Dunfrey Road
* **Entity Locality** - The locality of the entity that created the website, e.g.: Lansing
* **Entity Region** - The region of the entity that created the website, e.g.: Michigan or MI
* **Entity Postal Code** - The postal code of the entity that created the website, e.g.: 11360
* **Entity Country** - The country in which the entity that created the website is located, e.g.: US
#### Organization Info
* **Organization DUNS Number** - The DUNS (Dun & Bradstreet) number of the organization/company/restaurant that created the website
* **Organization Founder** - The name of the founder of the organization/company
* **Organization Founding Date** - The date the organization/company was founded
* **Organization Founding Location** - The location where the organization/company was founded
* **Organization Contact Points** - Use [organization contact points](https://developers.google.com/structured-data/customize/contact-points) to add your organizations's contact information to the Google Knowledge panel in some searches. The Telephone Number must be an internationalized version of the phone number, starting with the '+' symbol and country code (+1 in the US and Canada). e.g.: +1-800-555-1212 or +44-2078225951
#### Corporation Info
* **Corporation Ticker Symbol** - The exchange ticker symbol of the corporation
#### Person Info
* **Person Gender** - The gender of the person
* **Person Birth Place** - The place where the person was born
#### Humans.txt
* **Humans.txt Template** - [Humans.txt](http://humanstxt.org) is an initiative for knowing the people behind a website. It's a TXT file that contains information about the different people who have contributed to building the website. This is the template used to render it; you have access to all of the SEOmatic variables. This is the template used to render it; you have access to all of the SEOmatic variables.
The **Preview Humans.txt** button lets you preview what your rendered Humans.txt file will look like.
You can use any Craft `environmentVariables` in these fields in addition to static text, e.g.:
This is my {baseUrl}
### SEO Template Meta
This list of Template Metas will initially be empty; click on the **New Template Meta** button to create one.
These SEO Meta settings are used to render the SEO Meta for your website. You can create any number of SEO Template Metas associated with your Twig templates on your website.
They are used in combination with the SEO Template Meta settings to generate [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview), [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph), and as well as HTML meta tags.
If no Template Meta exists for a template, the SEO Site Meta is used.
If any fields are left blank in a Template Meta, those fields are pulled from the SEO Site Meta.
You can also dynamically change any of these SEO Meta fields in your Twig templates, and they will appear in the rendered SEO Meta.
* **Title** - The human readable title for this SEO Template Meta
* **Template Path** - Enter the path to the template to associate this meta with (just as you would on the Section settings). It will override the SEO Site Meta for this template. Leave any field blank if you want it to fall back on the default global settings for that field.
* **Main Entity of Page** - The Main Entity of Page is a more specific, additional type that describes this page. This additional JSON-LD structured data entity will be added to your page, more specifically describing the page's content. It is accessible via the `seomaticMainEntityOfPage` Twig variable, should you wish to modify or add to it
* **SEO Title** - This should be between 10 and 70 characters (spaces included). Make sure your title tag is explicit and contains your most important keywords. Be sure that each page has a unique title tag.
* **SEO Description** - This should be between 70 and 160 characters (spaces included). Meta descriptions allow you to influence how your web pages are described and displayed in search results. Ensure that all of your web pages have a unique meta description that is explicit and contains your most important keywords.
* **SEO Keywords** - Google ignores this tag; though other search engines do look at it. Utilize it carefully, as improper or spammy use most likely will hurt you, or even have your site marked as spam. Avoid overstuffing the keywords and do not include keywords that are not related to the specific page you place them on.
* **SEO Image** - This is the image that will be used for display as the webpage brand for this template, as well as on Twitter Cards and Facebook OpenGraph that link to this page, if they are not specified. The image must be in JPG, PNG, or GIF format.
* **SEO Image Transform** - The image transform to apply to the Site SEO Image.
* **Twitter Card Type** - With Twitter Cards, you can attach rich photos and information to Tweets that drive traffic to your website. Users who Tweet links to your content will have a “Card” added to the Tweet that’s visible to all of their followers.
* **Twitter Card Image** - This is the image that will be used for Twitter Cards that link to this page. If no image is specified here, the Site SEO Image will be used for Twitter Cards instead. The image must be in JPG, PNG, or GIF format.
* **Twitter Card Image Transform** - The image transform to apply to the Twitter Card Image. Twitter recommends: 120 x 120 pixels minimum size, 1:1 aspect ratio, 1mb max size for Summary Card images, and 280x150 pixels minimum size, 1.86:1 aspect ratio, 1mb max size for Summary Card with Large Image images.
* **Facebook OpenGraph Type** - Adding OpenGraph tags to your website influences the performance of your links on social media by allowing you to control what appears when a user posts a link to your content on Facebook.
* **Facebook OpenGraph Image** - This is the image that will be used for Facebook posts that link to this page. If no image is specified here, the Site SEO Image will be used for Facebook posts instead. The image must be in JPG, PNG, or GIF format.
* **Facebook OpenGraph Image Transform** - The image transform to apply to the Facebook OpenGraph Image. Facebook recommends: 1200 x 630 pixels minimum size, 1.9:1 aspect ratio, 8mb max size.
* **Robots** - The [robots meta tag](https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag?hl=en) lets you utilize a granular, page-specific approach to controlling how an individual page should be indexed and served to users in search results. Setting it to a blank value means 'no change'.
The **SEO Title**, **SEO Description**, and **SEO Keywords** fields can include tags that output entry properties, such as `{title}` or `{myCustomField}` in them.
You can use any Craft `environmentVariables` in these fields in addition to static text, e.g.:
This is my {baseUrl}
## SEO Entry Meta

SEOmatic provides a FieldType called `SEOmatic Meta` that you can add to your Sections. It allows you to provide meta information on a per-entry basis. SEOmatic will automatically override any Site Meta or Tempalate Meta with Entry Meta if an `entry` that has an SEOmatic Meta field is auto-populated by Craft into a template.
This also works with Categories and Craft Commerce Products that have an SEOmatic Meta field attached to them.
If you add an SEOmatic FieldType to an existing Section that already has entries in it, you'll need to re-save the Section to populate the newly added SEOmatic FieldType with data. You can do this via Settings → Edit My Section → hit Save.
If any fields are left blank in an Entry Meta, those fields are pulled from the SEO Site Meta / SEO Template Meta.
You can also dynamically change any of these SEO Meta fields in your Twig templates, and they will appear in the rendered SEO Meta.
* **Main Entity of Page** - The Main Entity of Page is a more specific, additional type that describes this entry. This additional JSON-LD structured data entity will be added to your page, more specifically describing the page's content. It is accessible via the `seomaticMainEntityOfPage` Twig variable, should you wish to modify or add to it.
* **SEO Title** - This should be between 10 and 70 characters (spaces included). Make sure your title tag is explicit and contains your most important keywords. Be sure that each page has a unique title tag.
* **SEO Description** - This should be between 70 and 160 characters (spaces included). Meta descriptions allow you to influence how your web pages are described and displayed in search results. Ensure that all of your web pages have a unique meta description that is explicit and contains your most important keywords.
* **SEO Keywords** - Google ignores this tag; though other search engines do look at it. Utilize it carefully, as improper or spammy use most likely will hurt you, or even have your site marked as spam. Avoid overstuffing the keywords and do not include keywords that are not related to the specific page you place them on.
* **SEO Image** - This is the image that will be used for display as the webpage brand for this entry, as well as on Twitter Cards and Facebook OpenGraph that link to this page, if they are not specified. The image must be in JPG, PNG, or GIF format.
* **Canonical URL Override** - The canonical URL is automatically set to the entry's URL. This allows you to override the canonical URL if you need to; this can be a path or a fully qualified URL. Just leave it blank for the canonical URL to be set automatically.
* **SEO Image Transform** - The image transform to apply to the Site SEO Image.
* **Twitter Card Type** - With Twitter Cards, you can attach rich photos and information to Tweets that drive traffic to your website. Users who Tweet links to your content will have a “Card” added to the Tweet that’s visible to all of their followers.
* **Twitter Card Image** - This is the image that will be used for display on Twitter Cards for tweets that link to this entry. If no image is specified here, the Site SEO Image will be used for Twitter Cards instead. The image must be in JPG, PNG, or GIF format.
* **Twitter Card Image Transform** - The image transform to apply to the Twitter Card Image. Twitter recommends: 120 x 120 pixels minimum size, 1:1 aspect ratio, 1mb max size for Summary Card images, and 280x150 pixels minimum size, 1.86:1 aspect ratio, 1mb max size for Summary Card with Large Image images.
* **Facebook OpenGraph Type** - Adding OpenGraph tags to your website influences the performance of your links on social media by allowing you to control what appears when a user posts a link to your content on Facebook.
* **Facebook OpenGraph Image** - This is the image that will be used for display on Facebook posts that link to this entry. If no image is specified here, the Site SEO Image will be used for Facebook posts instead. The image must be in JPG, PNG, or GIF format.
* **Facebook OpenGraph Image Transform** - The image transform to apply to the Facebook SEO Image. Facebook recommends: 1200 x 630 pixels minimum size, 1.9:1 aspect ratio, 8mb max size.
* **Robots** - The [robots meta tag](https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag?hl=en) lets you utilize a granular, page-specific approach to controlling how an individual page should be indexed and served to users in search results. Setting it to a blank value means 'no change'.
The **SEO Title**, **SEO Description**, and **SEO Keywords** fields can include tags that output entry properties, such as `{title}` or `{myCustomField}` in them.
You can use any Craft `environmentVariables` in these fields in addition to static text, e.g.:
This is my {baseUrl}
In addition to being able to hold custom data that you enter manually, you can also set the Source that **SEO Title**, **SEO Description**, **SEO Keywords**, and **SEO Image** SEOmatic Meta fields to pull data from to an existing field in your Entry.
**SEO Image** only can pull from an existing Assets field, while **SEO Title**, **SEO Description**, and **SEO Keywords** can pull from Text, Rich Text, Tags, and Matrix fields. If you pull from a Matrix field, SEOmatic goes through and concatenates all of the Text & Rich Text fields together (this is useful for **SEO Keywords** generation).
The **SEO Keywords** field also allows you to extract keywords automatically from an existing field in your Entry via the `Keywords From Field` Source option.
SEOmatic Meta FieldTypes also have default settings that allow you to control what the default settings should be for each meta field, and whether they can be changed by the person editing the entry.
### Entry Meta Properties in your Templates
If you're using an `SEOmatic Meta` FieldType in your entries, you can also access the properties of it in your templates. This is useful, for instance, if you're iterating through `craft.entries` and want to be able to access the meta properties of each entry in the loop.
Assume that we have an `SEOmatic Meta` FieldType with the handle `seoMeta` in our template, we can do things like:
{% for newsItem in craft.entries.section('news').limit(10) %}
{{ newsItem.seoMeta.seoTitle }}
{{ newsItem.seoMeta.seoDescription }}
{{ newsItem.seoMeta.seoKeywords }}
{{ newsItem.seoMeta.seoImage }}
{% endfor %}
In addition, you can do:
{% set assetID = newsItem.seoMeta.seoImageId %}
...to get the seoImage's AssetID, and you can also do:
{% set newsJsonLD = newsItem.seoMeta.getJsonLD(newsItem) %}
...to get the Main Entity of Page JSON-LD array for the entry, which you can then manipulate, or output via SEOmatic's Twig function:
{{ newsJsonLD | renderJSONLD }}
## SEOmetrics Content Analysis
The SEOmetrics feature in SEOmatic allows you to analyze your pages to measure the effectiveness of the SEO on them. It can be accessed in two different places, either analyzing arbitrary URLs via the Admin CP, or analyzing specific Entries/Sections via Live Preview.
### SEOmetrics in the Admin CP

SEOmetrics Content Analysis will run a variety of tests on your web page, and offer you analysis with helpful tips on how to correct any problems it finds. For each test, there is a `Learn More` link that will offer details on the thing being tested.
You can enter any arbitrary URL in the **URL to Analyze** field, even URLs to external websites, should you wish to.
You can enter **Focus Keyworks**, comma separated, for an additional analysis of how well optimized your page is for those specific SEO keywords.
### SEOmetrics during Live Preview

During Live Preview, a small SEOmatic icon is displayed in the lower-left corner of the Live Preview screen. If you click on it, it will run a variety of tests on your web page, and offer you analysis with helpful tips on how to correct any problems it finds.
You can enter **Focus Keyworks**, comma separated, for an additional analysis of how well optimized your page is for those specific SEO keywords.
### Video SEOmetrics in Action:
[](https://www.youtube.com/watch?v=y7swBbGwEJE)
You can disable this feature by setting `displaySeoMetrics` to `false` in the `config.php`, should you wish to not have it displayed.
SEOmetrics during Live Preview only works if System Status is set to "on".
## Craft Commerce Product Microdata

If an SEOmatic FieldType is attached to a Craft Commerce Product, in addition to rendering the page SEO Meta, it will also generate [Product JSON-LD microdata](https://developers.google.com/structured-data/rich-snippets/products) that describes the product.
It does this by pulling values from the `seomaticMeta` settings from the SEOmatic FieldType, as well as by pulling data from the Craft Commerce Product. If you have an SEOmatic FieldType attached to a Craft Commerce Product, `seomaticMainEntityOfPage` array is injected into your page template:
{% set seomaticMainEntityOfPage = [
{
type: "Product",
name: "Romper for a Red Eye",
description: "Irresistible to women. Establishes dominance over men. Brad's for Men will release your inner beast with its musky essence.",
image: "http://bradsformen.dev/img/site/site_logo.png",
logo: "http://bradsformen.dev/img/site/site_logo.png",
url: "http://bradsformen.dev/commerce/products/romper-for-a-red-eye",
sku: "Romper for a Red Eye",
offers: {
type: "Offer",
url: "http://bradsformen.dev/commerce/products/romper-for-a-red-eye",
price: "30.00",
priceCurrency: "USD",
offeredBy: seomaticIdenity,
seller: seomaticIdenity,
}
}
] %}
Since this is just a Twig array, you can alter it as you see fit, and whatever changes you make will be reflected in the JSON-LD that SEOmatic renders via the `{% hook 'seomaticRender' %}` Because of the way that Twig handles arrays, you **must** include every field in the array when doing a `set` or `merge`, otherwise the fields you exclude will not exist.
Or if you want to set just one variable in the array, you can use the Twig function [merge](http://twig.sensiolabs.org/doc/filters/merge.html). Because this is an _array_ of Products, you need to do something like this to add to each Product in the array:
{% if seomaticMainEntityOfPage is defined %}
{% set productBrand = {
'type': 'thing',
'name': product.title
}
%}
{% set tempMainEntityOfPage = [] %}
{% for productJsonLd in seomaticMainEntityOfPage %}
{% set productJsonLd = productJsonLd | merge({"brand": productBrand }) %}
{% set tempMainEntityOfPage = tempMainEntityOfPage |merge([productJsonLd]) %}
{% endfor %}
{% set seomaticMainEntityOfPage = tempMainEntityOfPage %}
{% endif %}
You can change these `seomaticMainEntityOfPage` variables in your templates that `extends` your main `layout.twig` template, and due to the Twig rendering order, when `{% hook 'seomaticRender' %}` is called, they'll be populated in your rendered SEO Meta tags.
See the section **Dynamic Twig SEO Meta** for more information on how to manipulate SEOmatic variables via Twig.
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
## Main Entity of Page Microdata

SEOmatic will automatically generate [Main Entity of Page](http://www.seoskeptic.com/how-to-use-schema-org-v2-0s-mainentityofpage-property/) JSON-LD microdata for Template and Entry SEO Meta.
The Main Entity of Page is a more specific, additional type of information that describes the page. This additional JSON-LD structured data entity will be added to your page, more specifically describing the page's content. It is accessible via the `seomaticMainEntityOfPage` Twig variable.
If an SEOmatic FieldType is attached to a Craft Commerce Product, SEOmatic will automatically extrapolate information from the Product. Otherwise, you can choose your own Main Entity of Page in the SEOmatic FieldType.
SEOmatic fills in the basic information for whatever schema type you set as the Main Entity of Page, but since this is just a Twig array, you can alter it as you see fit, and whatever changes you make will be reflected in the JSON-LD that SEOmatic renders via the `{% hook 'seomaticRender' %}` Because of the way that Twig handles arrays, you **must** include every field in the array when doing a `set` or `merge`, otherwise the fields you exclude will not exist.
Here's an example of how you might add a `startDate` to an `Event` schema type:
{% if seomaticMainEntityOfPage is defined %}
{% set eventStartDate = entry.eventDate %}
{% set seomaticMainEntityOfPage = seomaticMainEntityOfPage | merge({'startDate': eventStartDate }) %}
{% endif %}
Note that `Event` schema types require `startDate` and `location` to be set, which SEOmatic is unable to automatically fill in for you. Additionally, you may want to add more information to any of the schema types used for Main Entity of Page to give search engines more information to add to their knowledge graph.
### Gated or Subscription Content
Google recommends the use of JSON-LD Structured Data for [Subscription and paywalled content](https://developers.google.com/search/docs/data-types/paywalled-content). This is strongly encouraged, so that you are not errantly punished for violating Google's [cloaking](https://support.google.com/webmasters/answer/66355) policies or [guidelines](https://support.google.com/webmasters/answer/35769).
Whether your content is available only after a free registration process, or it's available only to people who subscribe to your website, it's recommended that you use this markup to help Google understand your content.
SEOmatic makes it easy to add this to your `MainEntityOfPage` using markup such as this in your Twig template:
```
{% if seomaticMainEntityOfPage is defined %}
{% set seomaticMainEntityOfPage = seomaticMainEntityOfPage | merge({
'isAccessibleForFree': 'False',
'hasPart': {
'type': 'WebPageElement',
'isAccessibleForFree': 'False',
'cssSelector': '.paywall',
}
}) %}
{% endif %}
```
Where the `.paywall` class is whatever your CSS selector is for blocking access to your content. If you have more then one, you'd do something like:
```
{% if seomaticMainEntityOfPage is defined %}
{% set seomaticMainEntityOfPage = seomaticMainEntityOfPage | merge({
'isAccessibleForFree': 'False',
'hasPart': [
{
'type': 'WebPageElement',
'isAccessibleForFree': 'False',
'cssSelector': '.paywall',
},
{
'type': 'WebPageElement',
'isAccessibleForFree': 'False',
'cssSelector': '#blocksContent',
}
]
}) %}
{% endif %}
```
For more information, see Googe's support article [Subscription and paywalled content](https://developers.google.com/search/docs/data-types/paywalled-content).
## Breadcrumbs Microdata

SEOmatic will automatically generate [Breadcrumbs](https://developers.google.com/search/docs/data-types/breadcrumbs) JSON-LD microdata that is used by Google to display breadcrumbs on the SERP rich cards.
By default, SEOmatic will generate breadcrumbs automatically for `Home` (the name is configurable via `breadcrumbsHomeName` in `config.json`), and every element (category, entry, product, whatever) that has a URI matches the current URL segments.
### Changing Breadcrumbs
If you want to do your own custom breadcrumbs, you can set them yourself in the `breadcrumbs` array in the `seomaticMeta` variable like this:
{% set myBreadcrumbs = {
"Home": "http://nystudio107.dev/",
"Books": "http://nystudio107.dev/books/",
"Candide": "http://nystudio107.dev/books/candide",
} %}
{% set seomaticMeta = seomaticMeta | merge({'breadcrumbs': myBreadcrumbs }) %}
{% if seomaticMainEntityOfPage is defined and seomaticMainEntityOfPage.type == "WebPage" %}
{% set seomaticMainEntityOfPage = seomaticMainEntityOfPage | merge({'breadcrumbs': myBreadcrumbs }) %}
{% endif %}
Since this is just a Twig array, you can alter it as you see fit, and whatever changes you make will be reflected in the JSON-LD that SEOmatic renders via the `{% hook 'seomaticRender' %}` Because of the way that Twig handles arrays, you **must** include every field in the array when doing a `set` or `merge`, otherwise the fields you exclude will not exist.
You can change these `breadcrumbs` variables in your templates that `extends` your main `layout.twig` template, and due to the Twig rendering order, when `{% hook 'seomaticRender' %}` is called, they'll be populated in your rendered SEO Meta tags.
See the section **Dynamic Twig SEO Meta** for more information on how to manipulate SEOmatic variables via Twig.
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
### Displaying Breadcrumbs on the Frontend
Should you wish to display the breadcrumbs in your front-end templates so that they are visible to the user, you can do that with code like this:
<ul class="crumbs">
{% for crumbName, crumbUrl in seomaticMeta.breadcrumbs %}
<li class="crumbs"><a href="{{ crumbUrl }}">{{ crumbName }}</a></li>
{% endfor %}
</ul>
## Dynamic Twig SEO Meta
All this SEO is great, but what if you want to generate dynamic SEO in an Twig template, with custom or specific requirements that the SEOmatic FieldType can't handle? SEOmatic makes it easy.
SEOmatic populates your templates with the following global variables for SEO Meta:
seomaticMeta.seoTitle
seomaticMeta.seoDescription
seomaticMeta.seoKeywords
seomaticMeta.seoImage
seomaticMeta.canonicalUrl
By default, `seomaticMeta.canonicalUrl` is set to `craft.request.url`.
All of the variables are set by a combination of your SEO Site Meta settings, and the SEO Template Meta settings linked to the currently rendered template (if any). These are the primary SEOmatic variables that you will be manipulating in your templates.
By the time the various SEOmatic variables are populated into your template, SEOmatic has applied all of the cascading meta from your Site Meta, Template Meta, and Entry Meta. The variables are all set, and will not be manipulated further by SEOmatic, only output.
So you can change the variables as you see fit; but it also means that if you change your `seoImage`, for example, it will not change the `og:image`. This is so that you can manipulate them independently.
**Important:** Due to the way Twig scoping works, if you `{% include %}` a template, it's given a copy of the current Twig context (variables, etc.), which means that any changes made there are not propagated back to the parent template.
So for instance if you `{% include %}` a template that changes some SEOmatic variables, they will **not** be changed in the parent context's scope, so they will not be rendered by SEOmatic.
You'll need to modify the SEOmatic variables in a template that `{% extends %}` the main `layout.twig` template or via Twig `embeds`.
These work like any other Twig variables; you can output them by doing:
{{ seomaticMeta.seoTitle }}
If you have a **Twitter Handle**, you'll also get variables that are used to generate your Twitter Card tags:
seomaticMeta.twitter.card
seomaticMeta.twitter.site
seomaticMeta.twitter.creator
seomaticMeta.twitter.title
seomaticMeta.twitter.description
seomaticMeta.twitter.image
You'll also get variables that are used to generate your Facebook Open Graph tags:
seomaticMeta.og.type
seomaticMeta.og.locale
seomaticMeta.og.url
seomaticMeta.og.title
seomaticMeta.og.description
seomaticMeta.og.image
seomaticMeta.og.site_name
seomaticMeta.og.see_also
When SEOmatic goes to render the `twitter`, `og` and `article` namespace tags, it iterates through the respective arrays, so you can add, remove, or change any of the key-value pairs in the array, and they will be rendered. Just ensure that the `key` is a valid schema type for the respective meta tags.
You can even do fun things like:
{% set seomaticMeta = seomaticMeta | merge({
og: {
type: seomaticMeta.og.type,
locale: seomaticMeta.og.locale,
url: entry.url,
title: "Some Title",
description: entry.summary,
image: ['one.jpg', 'two.jpg', 'three.jpg'],
site_name: seomaticMeta.og.site_name,
see_also: seomaticMeta.og.see_also
}
}) %}
...and SEOmatic will output 3 `og:image` tags, one for each image in the array. Because of the way that Twig handles arrays, you **must** include every field in the array when doing a `set` or `merge`, otherwise the fields you exclude will not exist.
You can also change them all at once like this using the Twig [set](http://twig.sensiolabs.org/doc/tags/set.html) syntax:
{% set seomaticMeta = {
seoTitle: "Some Title",
seoDescription: entry.summary,
seoKeywords: "Some,Key,Words",
seoImage: seomaticMeta.seoImage,
canonicalUrl: entry.url,
twitter: {
card: seomaticMeta.twitter.card,
site: seomaticMeta.twitter.site,
creator: seomaticMeta.twitter.creator,
title: "Some Title",
description: entry.summary,
image: seomaticMeta.twitter.image
},
og: {
type: seomaticMeta.og.type,
locale: seomaticMeta.og.locale,
url: entry.url,
title: "Some Title",
description: entry.summary,
image: seomaticMeta.og.image,
site_name: seomaticMeta.og.site_name,
see_also: seomaticMeta.og.see_also
}
} %}
Anywhere we are setting a field to `seomaticMeta.*`, we're setting it to what it already is, essentially saying to leave it unchanged. We do this because Twig requires that you pass in the entire array to the `set` operator.
If you're using the `article` OpenGraph type, you'll see an additional `article` namespace array in your `seomaticMeta`:
{% set seomaticMeta = {
seoTitle: "Some Title",
seoDescription: entry.summary,
seoKeywords: "Some,Key,Words",
seoImage: seomaticMeta.seoImage,
canonicalUrl: entry.url,
twitter: {
card: seomaticMeta.twitter.card,
site: seomaticMeta.twitter.site,
creator: seomaticMeta.twitter.creator,
title: "Some Title",
description: entry.summary,
image: seomaticMeta.twitter.image
},
og: {
type: seomaticMeta.og.type,
locale: seomaticMeta.og.locale,
url: entry.url,
title: "Some Title",
description: entry.summary,
image: seomaticMeta.og.image,
site_name: seomaticMeta.og.site_name,
see_also: seomaticMeta.og.see_also
},
article: {
author: "Some Author",
publisher: "Some publisher",
tag: "some,tags"
}
} %}
Or if you want to set just one variable in the array, you can use the Twig function [merge](http://twig.sensiolabs.org/doc/filters/merge.html):
{% set seomaticMeta = seomaticMeta | merge({'seoDescription': entry.summary }) %}
Here's an example of how to change just the `image` in Twitter:
{% set twitter = seomaticMeta.twitter %}
{% set twitter = twitter | merge({'image': someiImage}) %}
{% set seomaticMeta = seomaticMeta | merge({'twitter': twitter}) %}
...and here's an example of how to change just the `image` in OpenGraph:
{% set og = seomaticMeta.og %}
{% set og = og | merge({'image': someiImage}) %}
{% set seomaticMeta = seomaticMeta | merge({'og': og}) %}
You can change these `seomaticMeta` variables in your templates that `extends` your main `layout.twig` template, and due to the Twig rendering order, when `{% hook 'seomaticRender' %}` is called, they'll be populated in your rendered SEO Meta tags.
Some of the `seomaticMeta` variables have character limitations on them, because search engines want to see only the most relevant, succinct information, and will truncate them during processing:
* **seomaticMeta.seoTitle** - 70 characters
* **seomaticMeta.seoDescription** - 160 characters
* **seomaticMeta.seoKeywords** - 200 characters
SEOmatic will automatically truncate these variables for you when you set them, so you don't have to worry about the length. It intelligently truncates them on whole-word boundaries, so nothing will get cut off.
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
## Rendering Custom JSON LD Microdata
SEOmatic gives you the ability to render an arbitrary [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) object, passed in as an array(). All three of these methods accomplish the same thing:
{# Render arbitrary JSON-LD using the 'renderJSONLD' function #}
{{ renderJSONLD( JSONLD_ARRAY ) }}
{# Render arbitrary JSON-LD using the 'renderJSONLD' filter #}
{{ JSONLD_ARRAY | renderJSONLD }}
{# Render arbitrary JSON-LD using the 'renderJSONLD' variable #}
{% do craft.seomatic.renderJSONLD( JSONLD_ARRAY ) %}
The JSONLD_ARRAY should be in the following format in PHP:
$myJSONLD = array(
"type" => "Corporation",
"name" => "nystudio107",
"sameAs" => ["https://Twitter.com/nystudio107","https://plus.google.com/+nystudio107"],
"address" => array(
"type" => 'PostalAddress',
"addressCountry" => "US",
),
);
The JSONLD_ARRAY should be in the following format in Twig:
{% set myJSONLD = {
"type": "Corporation",
"name": "nystudio107",
"sameAs": ["https://Twitter.com/nystudio107","https://plus.google.com/+nystudio107"],
"address": {
"type": 'PostalAddress',
"addressCountry": "US",
},
} %}
The above arrays will render to the following JSON-LD:
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Corporation",
"name": "nystudio107",
"sameAs": ["https://Twitter.com/nystudio107","https://plus.google.com/+nystudio107"],
"address": {
"@type": "PostalAddress",
"addressCountry": "US"
}
}
</script>
The array can be nested arbitrarily deep with sub-arrays. The first key in the array, and in each sub-array, should be an "type" with a valid [Schema.org](http://Schema.org) type as the value. Because Twig doesn't support array keys with non-alphanumeric characters, SEOmatic transforms the keys "type" into "@type" at render time.
Here's a practical example. Let's say you're working on a spiffy new online store using Craft Commerce, and you want to add in some microdata for the products listed in your store, for SEO purposes. You can do something like this:
{% set myJSONLD = {
type: "Product",
name: "Brad's for Men Cologne",
image: "http://bradsformen.com/cologne.png",
logo: "http://bradsformen.com/cologne_logo.png",
description: "Brad Bell's musky essence will intoxicate you.",
model: "XQJ-37",
offers: {
type: "Offer",
url: "http://bradsformen.com/cologne",
price: "69.99",
priceCurrency: "USD",
acceptedPaymentMethod: ["CreditCard", "PayPal"],
seller: {
type: "Corporation",
name: "Brad Brands Intl.",
url: "http://bradsformen.com"
}
},
manufacturer: {
type: "Organization",
name: "Scents Unlimited",
url: "http://scentsunlimited.com"
},
aggregateRating: {
type: "AggregateRating",
bestRating: "100",
ratingCount: "24",
ratingValue: "87"
},
} %}
{{ myJSONLD | renderJSONLD }}
Obviously, you'll want to substitute in variables for the above, e.g.:
{% set products = craft.commerce.products.type('normal').find() %}
{% for product in products %}
{% for variant in products.variants %}
{% set myJSONLD = {
type: "Product",
name: variant.description,
image: variant.myProductShot,
logo: variant.myProductLogo,
description: variant.myProductDescription,
model: variant.myProductModel,
offers: {
type: "Offer",
url: product.url,
price: variant.price,
priceCurrency: "USD",
acceptedPaymentMethod: ["CreditCard", "PayPal"],
seller: {
type: "Corporation",
name: seomaticSiteMeta.siteSeoName,
url: siteUrl
}
}
} %}
{{ myJSONLD | renderJSONLD }}
{% endfor %}
{% endfor %}
There are many other values available for you to use; see the [Product](https://developers.google.com/schemas/reference/types/Product) schema for details.
Here's another practical example of custom JSON-LD microdata to generate a `MusicAlbum`:
{% set musicAlbumJsonLd = {
type: "MusicAlbum",
name: entry.albumTitle | escape('html_attr'),
image: entry.albumArtwork.first().url |default(seomaticMeta.seoImage),
description: entry.albumDescription | escape('html_attr'),
url: seomaticMeta.canonicalUrl,
albumProductionType: 'studio album',
datePublished: entry.postDate.iso8601(),
sameAs: [entry.amazonLink, entry.appleMusicLink, entry.itunesLink, entry.spotifyLink]
} %}
{% set musicAlbumJsonLd = musicAlbumJsonLd | merge({"author": seomaticIdentity}) %}
{% set musicAlbumJsonLd = musicAlbumJsonLd | merge({"creator": seomaticIdentity}) %}
{% set musicAlbumJsonLd = musicAlbumJsonLd | merge({"byArtist": seomaticIdentity}) %}
{{ musicAlbumJsonLd | renderJSONLD }}
Additional information links:
* [Google Structured Data](https://developers.google.com/structured-data/)
* [Google Schemas reference](https://developers.google.com/schemas/reference/)
* [Schema.org Schemas reference](http://schema.org/docs/schemas.html)
## Dynamic Keyword Generation
Generating good keywords from dynamic data is a pain; to this end, SEOmatic uses the [TextRank](https://github.com/crodas/TextRank) PHP library to generate high quality keywords from arbitrary text data.
All three of these methods accomplish the same thing:
{# Extract keywords using the 'extractKeywords' function #}
{{ extractKeywords( TEXT, LIMIT ) }}
{# Extract keywords using the 'extractKeywords' filter #}
{{ TEXT | extractKeywords( LIMIT ) }}
{# Extract keywords using the 'extractKeywords' variable #}
{% do craft.seomatic.extractKeywords( TEXT, LIMIT ) %}
**TEXT** is the text to extract the keywords from, and the optional **LIMIT** parameter specifies the maximum number of keywords to return (the default is 15).
Here's an example use of the `extractKeywords()` function:
{{ extractKeywords('Scientists have developed a gel that helps brains
recover from traumatic injuries. It has the potential to treat head injuries
suffered in combat, car accidents, falls, or gunshot wounds. Developed by
Dr. Ning Zhang at Clemson University in South Carolina, the gel is injected
in liquid form at the site of injury and stimulates the growth of stem cells
there. Brain injuries are particularly hard to repair, since injured tissues
swell up and can cause additional damage to the cells. So far, treatments
have tried to limit this secondary damage by lowering the temperature or
relieving the pressure at the site of injury. However, these techniques are
often not very effective. More recently, scientists have considered
transplanting donor brain cells into the wound to repair damaged tissue.
This method has so far had limited results when treating brain injuries. The
donor cells often fail to grow or stimulate repair at the injury site,
possibly because of the inflammation and scarring present there. The injury
site also typically has very limited blood supply and connective tissue,
which might prevent donor cells from getting the nutrients they require. Dr.
Zhangs gel, however, can be loaded with different chemicals to stimulate
various biological processes at the site of injury. In previous research
done on rats, she was able to use the gel to help re-establish full blood
supply at the site of brain injury. This could help create a better
environment for donor cells. In a follow-up study, Dr. Zhang loaded the gel
with immature stem cells, as well as the chemicals they needed to develop
into full-fledged adult brain cells. When rats with severe brain injuries
were treated with this mixture for eight weeks, they showed signs of
significant recovery. The new gel could treat patients at varying stages
following injury, and is expected to be ready for testing in humans in about
three years.') }}
This will output the following:
injury site, brain cells, brain injuries, donor cells, donor brain cells,
injury, site of injury, site, cells, brain, injuries, repair, donor, damage
to the cells, blood
So tying it all together, you might do something like this for a dynamic Blog entry:
{% set seomaticMeta = {
seoTitle: entry.title,
seoDescription: entry.summary,
seoKeywords: extractKeywords(entry.blog),
seoImage: entry.image.url,
canonicalUrl: seomaticMeta.canonicalUrl,
twitter: {
card: seomaticMeta.twitter.card,
site: seomaticMeta.twitter.site,
creator: seomaticMeta.twitter.creator,
title: entry.title,
description: entry.summary,
image: entry.image.url
},
og: {
type: seomaticMeta.og.type,
locale: seomaticMeta.og.locale,
url: entry.url,
title: entry.title,
description: entry.summary,
image: entry.image.url,
site_name: seomaticMeta.og.site_name,
see_also: seomaticMeta.og.see_also
}
} %}
And there you have it, dynamic keywords for your SEO Meta. Note that we set the `canonicalUrl` to `seomaticMeta.canonicalUrl`, effectively leaving it unchanged.
Anywhere we are setting a field to `seomaticMeta.*`, we're setting it to what it already is, essentially saying to leave it unchanged. We do this because Twig requires that you pass in the entire array to the `set` operator.
## Dynamic Summary Generation
Generating a good summary from dynamic data is also a pain; to this end, SEOmatic uses the [TextRank](https://github.com/crodas/TextRank) PHP library to generate a summary from arbitrary text data.
All three of these methods accomplish the same thing:
{# Extract a summary using the 'extractSummary' function #}
{{ extractSummary( TEXT, LIMIT ) }}
{# Extract a summary using the 'extractSummary' filter #}
{{ TEXT | extractSummary( LIMIT ) }}
{# Extract a summary using the 'extractSummary' variable #}
{% do craft.seomatic.extractSummary( TEXT, LIMIT ) %}
**TEXT** is the text to extract the summary from, and the optional **LIMIT** parameter specifies the maximum number of characters to return. The Summary is returns is at most 5% of the sentences of the text.
**Caveats** - This feature of TextRank seems to be best suited for large amounts of text. It attempts to pick out the most relevant whole sentences based on statistical analysis. The result may end up being too long to be useful for an `seoDescription` in some cases.
So tying it all together, you might do something like this for a dynamic Blog entry:
{% set seomaticMeta = {
seoTitle: entry.title,
seoDescription: extractSummary(entry.blog),
seoKeywords: extractKeywords(entry.blog),
seoImage: entry.image.url,
canonicalUrl: seomaticMeta.canonicalUrl,
twitter: {
card: seomaticMeta.twitter.card,
site: seomaticMeta.twitter.site,
creator: seomaticMeta.twitter.creator,
title: entry.title,
description: extractSummary(entry.blog),
image: entry.image.url
},
og: {
type: seomaticMeta.og.type,
locale: seomaticMeta.og.locale,
url: entry.url,
title: entry.title,
description: extractSummary(entry.blog),
image: entry.image.url,
site_name: seomaticMeta.og.site_name,
see_also: seomaticMeta.og.see_also
}
} %}
Note that we set the `canonicalUrl` to `seomaticMeta.canonicalUrl`, effectively leaving it unchanged.
Anywhere we are setting a field to `seomaticMeta.*`, we're setting it to what it already is, essentially saying to leave it unchanged. We do this because Twig requires that you pass in the entire array to the `set` operator.
## Humans.txt authorship
[Humans.txt](http://humanstxt.org) is an initiative for knowing the people behind a website. It's a TXT file that contains information about the different people who have contributed to building the website.
SEOmatic automatically generates [Humans.txt](http://humanstxt.org) authorship accreditation with the following tag:
<link type="text/plain" rel="author" href="/humans.txt" />
The rendered `humans.txt` file uses the following template by default (you're free to change it as you wish):
/* TEAM */
{% if seomaticCreator.name is defined and seomaticCreator.name %}
Creator: {{ seomaticCreator.name }}
{% endif %}
{% if seomaticCreator.url is defined and seomaticCreator.url %}
URL: {{ seomaticCreator.url }}
{% endif %}
{% if seomaticCreator.description is defined and seomaticCreator.description %}
Description: {{ seomaticCreator.description }}
{% endif %}
/* THANKS */
Pixel & Tonic - https://pixelandtonic.com
/* SITE */
Standards: HTML5, CSS3
Components: Craft CMS, Yii, PHP, Javascript, SEOmatic
## Utility Filters & Functions
SEOmatic exposes a few useful utility filters & functions that you can use... or not.
### truncateStringOnWord()
All three of these methods accomplish the same thing:
{# Truncate a string on word boundaries using the 'truncateStringOnWord' function #}
{{ truncateStringOnWord( THESTRING, DESIREDLENGTH ) }}
{# Truncate a string on word boundaries using the 'truncateStringOnWord' filter #}
{{ THESTRING | truncateStringOnWord( DESIREDLENGTH ) }}
{# Truncate a string on word boundaries using the 'truncateStringOnWord' variable #}
{% do craft.seomatic.truncateStringOnWord( THESTRING, DESIREDLENGTH ) %}
**THESTRING** is the string to be truncated, and the optional **DESIREDLENGTH** parameter specifies the desired length in characters. The returned string will be broken on a whole-word boundary, with an … appended to the end if it is truncated.
You shouldn't need to use truncateStringOnWord() for SEO Meta like `seoTitle` & `seoDescription` that have character limitations, because SEOmatic will truncate them for you automatically. However you may find this function handy for other purposes.
### extractTextFromMatrix()
All three of these methods accomplish the same thing:
{# Extract all and concatenate all of the text fields from a Matrix block using the 'extractTextFromMatrix' function #}
{{ extractTextFromMatrix( THEMATRIXBLOCK ) }}
{# Extract all and concatenate all of the text fields from a Matrix block using the 'extractTextFromMatrix' filter #}
{{ THEMATRIXBLOCK | extractTextFromMatrix() }}
{# Extract all and concatenate all of the text fields from a Matrix block using the 'extractTextFromMatrix' variable #}
{% do craft.seomatic. extractTextFromMatrix( THEMATRIXBLOCK ) %}
**THEMATRIXBLOCK** is the Matrix block to extract text from. It iterates through all of the 'Text' and 'Rich Text' fields in a Matrix block, and concatenates the text together for you. This is a useful precursor for the `extractKeywords()` function.
### encodeEmailAddress()
All three of these methods accomplish the same thing:
{# Ordinal-encode an email address to obfuscate it using the 'encodeEmailAddress' function #}
{{ encodeEmailAddress( EMAILADDRESS ) }}
{# Ordinal-encode an email address to obfuscate it using the 'encodeEmailAddress' filter #}
{{ EMAILADDRESS | encodeEmailAddress() }}
{# Ordinal-encode an email address to obfuscate it using the 'encodeEmailAddress' variable #}
{% do craft.seomatic.encodeEmailAddress( EMAILADDRESS ) %}
**EMAILADDRESS** is the email address to be ordinal-encoded. For instance, `info@nystudio107.com` becomes:
info@nystudio107.com
Google can still properly decode email addresses that are ordinal-encoded, it's still readable by humans when displayed, but it prevents some bots from recognizing it as an email address.
### getLocalizedUrls()
Returns an array of localized URLs for the current page request. This handles elements with localized slugs, etc. This function returns the unique URLs for each language for the current page request, not just the localized site URLs.
Both of these methods accomplish the same thing:
{# Get an array of localized URLs for the current request using the 'getLocalizedUrls' function #}
{% set myLocalizedUrls = getLocalizedUrls() }}
{# Get an array of localized URLs for the current request using the 'getLocalizedUrls' variable #}
{% set myLocalizedUrls = craft.seomatic.getLocalizedUrls() %}
You'll be returned an array that looks like this:
{
'en': 'http://nystudio107.dev/',
'el_gr': 'http://nystudio107.dev/gr/'
}
With a key/value pair for each language your site is localized in, in the order you have them set in the AdminCP. This makes it very easy to create a "language switcher" menu.
### getFullyQualifiedUrl()
All three of these methods accomplish the same thing:
{# Get a fully qualified URL based on the siteUrl using the 'getFullyQualifiedUrl' function #}
{{ getFullyQualifiedUrl( URLPATH ) }}
{# Get a fully qualified URL based on the siteUrl using the 'getFullyQualifiedUrl' filter #}
{{ URLPATH | getFullyQualifiedUrl }}
{# Get a fully qualified URL based on the siteUrl using the 'getFullyQualifiedUrl' variable #}
{% do craft.seomatic.getFullyQualifiedUrl( URLPATH ) %}
**URLPATH** is either a URL (in which case it is just returned) or a path, in which case it is combined with the `siteUrl` and returned.
## SEOmatic Site Meta Twig Variables
SEOmatic populates your templates with the following global variables for Site Meta:
seomaticSiteMeta.siteSeoName
seomaticSiteMeta.siteSeoTitle
seomaticSiteMeta.siteSeoDescription
seomaticSiteMeta.siteSeoKeywords
seomaticSiteMeta.siteSeoImage
seomaticSiteMeta.siteOwnerType
All of the variables are from your SEO Site Meta settings, and will be the same for every template rendered. They are for the most part very similar to your SEO Meta variables, but they do not change from template to template: they are site-wide.
Mostly, you won't need to change them in your Twig templates, but it can be useful to reference or output them. These work like any other Twig variables; you can output them by doing:
{{ seomaticSiteMeta.siteSeoName }}
You can also change these variables the same way you change the "Dynamic Twig SEO Meta" (using Twig `set` and `merge`), but in practice they typically will just be set in the SEOmatic **SEO Site Meta** settings page in the Admin CP.
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
## SEOmatic Site Identity Twig Variables
SEOmatic populates your templates with an array of Site Identity variables; see the **Rendered Identity Microdata** section for a complete listing of them. All of the variables are from your Site Identity settings, and will be the same for every template rendered.
Mostly, you won't need to change them in your Twig templates, but it can be useful to reference or output them. These work like any other Twig variables; you can output them by doing:
{{ seomaticIdentity.name }}
You can also change these variables the same way you change the "Dynamic Twig SEO Meta" (using Twig `set` and `merge`), but in practice they typically will just be set in the SEOmatic **Site Identity** settings page in the Admin CP.
Because the `seomaticIdentity` array is directly translated into JSON-LD, you can manipulate it via Twig to modify or add to the JSON-LD. For example, let's say you want to add a [Brand](https://schema.org/Brand) to your [Corporation](https://schema.org/Corporation)-type Identity JSON-LD:
{% set myBrand = {
type: "Brand",
name: "Brad's for Men",
description: "Brad Bell's musky essence will intoxicate you.",
url: "http://bradsformen.com",
logo: "http://bradsformen.com/logo.png",
image: "http://bradsformen.com/lifestyle.jpg",
} %}
{% set seomaticIdentity = seomaticIdentity | merge({'brand': myBrand }) %}
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
The `email` variable is ordinal-encoded to obfuscate it. For instance, `info@nystudio107.com` becomes:
info@nystudio107.com
## SEOmatic Social Media Twig Variables
SEOmatic populates your templates with the following global variables for Social Media:
seomaticSocial.twitterHandle
seomaticSocial.facebookHandle
seomaticSocial.facebookProfileId
seomaticSocial.linkedInHandle
seomaticSocial.googlePlusHandle
seomaticSocial.googleSiteVerification
seomaticSocial.youtubeHandle
seomaticSocial.instagramHandle
seomaticSocial.pinterestHandle
All of the variables are from your Social Media settings, and will be the same for every template rendered.
Mostly, you won't need to change them in your Twig templates, but it can be useful to reference or output them. These work like any other Twig variables; you can output them by doing:
{{ seomaticSocial.twitterHandle }}
You can also change these variables the same way you change the "Dynamic Twig SEO Meta" (using Twig `set` and `merge`), but in practice they typically will just be set in the SEOmatic **Social Media** settings page in the Admin CP.
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
## SEOmatic Site Creator Twig Variables
SEOmatic populates your templates with an array of Site Creator variables; see the **Rendered WebSite Microdata** section for a complete listing of them. All of the variables are from your Site Creator settings, and will be the same for every template rendered.
Mostly, you won't need to change them in your Twig templates, but it can be useful to reference or output them. These work like any other Twig variables; you can output them by doing:
{{ seomaticCreator.name }}
You can also change these variables the same way you change the "Dynamic Twig SEO Meta" (using Twig `set` and `merge`), but in practice they typically will just be set in the SEOmatic **Site Creator** settings page in the Admin CP.
Because the `seomaticCreator` array is directly translated into JSON-LD, you can manipulate it via Twig to modify or add to the JSON-LD. For example, let's say you want to add an `affiliation` to your [Person](https://schema.org/Person)-type Creator JSON-LD:
{% set myAffiliation = {
type: "Organization",
name: "nystudio107",
description: "Impeccable design married with precision craftsmanship.",
url: "http://nystudio107.com",
} %}
{% set seomaticCreator = seomaticCreator | merge({'affiliation': myAffiliation }) %}
SEOmatic also automatically strips HTML/PHP tags from the variables, and translates HTML entities to ensure that they are properly encoded.
The `email` variable is ordinal-encoded to obfuscate it. For instance, `info@nystudio107.com` becomes:
info@nystudio107.com
## SEOmatic Helper Twig Variables
SEOmatic populates your templates with the following "helper" variables for that you can use in your templates:
seomaticHelper.twitterUrl
seomaticHelper.facebookUrl
seomaticHelper.googlePlusUrl
seomaticHelper.linkedInUrl
seomaticHelper.youtubeUrl,
seomaticHelper.youtubeChannelUrl
seomaticHelper.instagramUrl
seomaticHelper.pinterestUrl
seomaticHelper.githubUrl
seomaticHelper.vimeoUrl
seomaticHelper.wikipediaUrl
seomaticHelper.ownerGoogleSiteVerification
seomaticHelper.ownerBingSiteVerification
seomaticHelper.ownerGoogleAnalyticsUID
seomaticHelper.ownerGoogleTagManagerID
seomaticHelper.googleAnalyticsSendPageview
seomaticHelper.googleAnalyticsAdvertising
seomaticHelper.googleAnalyticsEcommerce
seomaticHelper.googleAnalyticsEEcommerce
seomaticHelper.googleAnalyticsLinkAttribution
seomaticHelper.googleAnalyticsLinker
seomaticHelper.googleAnalyticsAnonymizeIp
seomaticHelper.ownerCopyrightNotice
seomaticHelper.ownerAddressString
seomaticHelper.ownerAddressHtml
seomaticHelper.ownerMapUrl
seomaticHelper.creatorCopyrightNotice
seomaticHelper.creatorAddressString
seomaticHelper.creatorAddressHtml
seomaticHelper.creatorMapUrl
## Previewing your SEO Meta
There's a lot going on here, so to make it all more easily understood, SEOmatic offers two ways to preview your SEO Meta. You have to **Save** the settings first before you preview them; a "Live Preview" feature is on the wish list for future versions.
### Preview SEO Meta Display

Clicking on the **Preview SEO Meta Display** button will show you a preview of what the rendered SEO Meta will look like to various services that scrape your SEO Meta tags, such as Google, Twitter, and Facebook.
This serves as a nice sanity check for you, and a very nice way to show clients the amazing job you did on their SEO strategy.
If you click on the **Preview SEO Meta Display** button when you are editing a SEO Template Meta, you'll see the result of that particular template's SEO Template Meta tags. Otherwise, you will see the SEO Site Meta tags.
### Preview SEO Meta Tags
Clicking on the **Preview SEO Meta Tags** button will show you Twig/HTML output of the following things:
#### Meta Template Variables
These are the Twig variables that SEOmatic pre-populates, and makes available to you in your templates. They are used when rendering the SEO Meta, so you can manipulate them however you want before rendering your SEO Meta. For example, you might change the `seomaticMeta.seoDescription` to be the summary field of an entry.
{% set seomaticMeta = {
seoTitle: "We make the big stuff big & the little stuff little",
seoDescription: "Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!",
seoKeywords: "colossal,considerable,enormous,fat,full,gigantic,hefty,huge,immense,massive,sizable,substantial,tremendous,",
seoImage: "http://nystudio107.dev/img/site/big_hq.jpg",
canonicalUrl: "http://nystudio107.dev/",
twitter: {
card: "summary_large_image",
site: "@nystudio107",
creator: "@nystudio107",
title: "We make the big stuff big & the little stuff little | Big Entity, Inc.",
description: "Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!",
image: "http://nystudio107.dev/img/site/big_hq.jpg"
},
og: {
type: "website",
locale: "en",
url: "http://nystudio107.dev/admin/seomatic/social",
title: "We make the big stuff big & the little stuff little | Big Entity, Inc.",
description: "Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!",
image: "http://nystudio107.dev/img/site/big_hq.jpg",
site_name: "Big Entity, Inc.",
see_also: ["https://twitter.com/nystudio107","https://www.facebook.com/nystudio107","https://plus.google.com/+nystudio107","https://www.linkedin.com/company/nystudio107","https://www.youtube.com/user/nystudio107","https://www.instagram.com/nystudio107","https://www.pinterest.com/nystudio107"]
}
} %}
{% set seomaticHelper = {
twitterUrl: "https://twitter.com/nystudio107",
facebookUrl: "https://www.facebook.com/nystudio107",
googlePlusUrl: "https://plus.google.com/+nystudio107",
linkedInUrl: "https://www.linkedin.com/company/nystudio107",
youtubeUrl: "https://www.youtube.com/user/nystudio107",
instagramUrl: "https://www.instagram.com/nystudio107",
pinterestUrl: "https://www.pinterest.com/nystudio107",
ownerGoogleSiteVerification: "BM6VkEojTIASDEWyTLro7VNhZnW_036LNdcYk5j9X_8g",
ownerCopyrightNotice: "Copyright ©2015 Big Entity, Inc. All rights reserved.",
ownerAddressString: "Big Entity, Inc., 123 Some Road, Porchester, NY 11450, USA",
ownerAddressHtml: "Big Entity, Inc.<br />123 Some Road<br />Porchester, NY 11450<br />USA<br />",
ownerMapUrl: "http://maps.google.com/maps?q=Big+Entity%2C+Inc.%2C+123+Some+Road%2C+Porchester%2C+NY+11450%2C+USA",
creatorCopyrightNotice: "Copyright ©2015 NY Studio 107. All rights reserved.",
creatorAddressString: "",
creatorAddressHtml: "",
creatorMapUrl: ""
} %}
{% set seomaticSiteMeta = {
siteSeoName: "Big Entity, Inc.",
siteSeoTitle: "We make the big stuff big & the little stuff little",
siteSeoDescription: "Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!",
siteSeoKeywords: "colossal,considerable,enormous,fat,full,gigantic,hefty,huge,immense,massive,sizable,substantial,tremendous,",
siteSeoImage: "http://nystudio107.dev/img/site/big_hq.jpg"
} %}
{% set seomaticSocial = {
twitterHandle: "nystudio107",
facebookHandle: "nystudio107",
facebookProfileId: "642246343",
linkedInHandle: "nystudio107",
googlePlusHandle: "nystudio107",
youtubeHandle: "nystudio107",
instagramHandle: "nystudio107",
pinterestHandle: "nystudio107"
} %}
{% set seomaticIdentity = {
type: "Corporation",
name: "Big Entity, Inc.",
alternateName: "Big",
description: "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
url: "http://BigEntity.com",
image: "http://nystudio107.dev/img/site/big_logo.jpg",
telephone: "585.214.9439",
email: "info@BigEntity.com",
address: {
type: "PostalAddress",
streetAddress: "123 Some Road",
addressLocality: "Porchester",
addressRegion: "NY",
postalCode: "11450",
addressCountry: "US"
},
logo: "http://nystudio107.dev/img/site/big_logo.jpg",
location: {
type: "Place",
name: "Big Entity, Inc.",
alternateName: "Big",
description: "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
hasMap: "http://maps.google.com/maps?q=Big+Entity%2C+Inc.%2C+123+Some+Road%2C+Porchester%2C+NY+11450%2C+USA",
geo: {
type: "GeoCoordinates",
latitude: "-10.447525",
longitude: "105.690449"
},
address: {
type: "PostalAddress",
streetAddress: "123 Some Road",
addressLocality: "Porchester",
addressRegion: "NY",
postalCode: "11450",
addressCountry: "US"
}
},
duns: "12345678",
founder: "Mr. Big",
foundingDate: "10/2011",
foundingLocation: "Redding, CT",
tickerSymbol: "BGE"
} %}
{% set seomaticCreator = {
type: "Corporation",
name: "NY Studio 107",
alternateName: "nystudio107",
description: "Impeccable design married with precision craftsmanship",
url: "http://nystudio107.com",
image: "http://nystudio107.dev/img/site/nys_seo_logo.png",
email: "info@nystudio107.com",
address: {
type: "PostalAddress",
addressLocality: "Webster",
addressRegion: "NY",
postalCode: "14580",
addressCountry: "US"
},
logo: "http://nystudio107.dev/img/site/nys_seo_logo.png",
location: {
type: "Place",
name: "NY Studio 107",
alternateName: "nystudio107",
description: "Impeccable design married with precision craftsmanship",
geo: {
type: "GeoCoordinates",
latitude: "43.11558",
longitude: "-77.59647199999999"
},
address: {
type: "PostalAddress",
addressLocality: "Webster",
addressRegion: "NY",
postalCode: "14580",
addressCountry: "US"
}
}
} %}
{% set seomaticTemplatePath = "" %}
You can treat all of these like regular Twig variables; for instance, `{{ seomaticHelper.twitterUrl }}` will output the URL to the website's Twitter page. You can change these variables using the Twig array [set](http://twig.sensiolabs.org/doc/tags/set.html) syntax, or using the Twig function [merge](http://twig.sensiolabs.org/doc/filters/merge.html). Any changes you make will be reflected in the SEO Meta rendered with `{% hook 'seomaticRender' %}` on your page.
#### Rendered SEO Meta
The `{% hook 'seomaticRender' %}` tag generates these SEO Meta for you, based on the Meta Template Variables (above). By default, it uses an internal template, but you can pass your own template to be used instead, like this: `{% set seomaticTemplatePath = 'path/template' %} {% hook 'seomaticRender' %}`
SEOmatic cascades Meta settings; if you have a Meta associated with the current template, it uses that. Otherwise it falls back on the SEO Site Meta settings. If a field is empty for a Template Meta, it falls back on the SEO Site Meta setting for that field.
<!-- BEGIN SEOmatic rendered SEO Meta -->
<title>[devMode] We make the big stuff big & the little stuff… | Big Entity, Inc.</title> <!-- {% if craft.config.devMode %}[devMode] {% endif %}{% if seomaticSiteMeta.siteSeoTitlePlacement == "before" %}{{ seomaticSiteMeta.siteSeoName |raw }}{% if seomaticMeta.seoTitle %} {{ seomaticSiteMeta.siteSeoTitleSeparator }} {% endif %}{% endif %}{{ seomaticMeta.seoTitle |raw }}{% if seomaticSiteMeta.siteSeoTitlePlacement == "after" %}{% if seomaticMeta.seoTitle %} {{ seomaticSiteMeta.siteSeoTitleSeparator }} {% endif %}{{ seomaticSiteMeta.siteSeoName |raw }}{% endif %} -->
<!-- Standard SEO -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="referrer" content="no-referrer-when-downgrade" />
<meta name="robots" content="all" /> <!-- {{ seomaticMeta.robots }} -->
<meta name="keywords" content="colossal, considerable, enormous, fat, full, gigantic, hefty, huge, immense, massive, sizable, substantial, tremendous" /> <!-- {{ seomaticMeta.seoKeywords }} -->
<meta name="description" content="Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!" /> <!-- {{ seomaticMeta.seoDescription }} -->
<meta name="generator" content="SEOmatic" /> <!-- SEOmatic -->
<link rel="canonical" href="http://nystudio107.dev/" /> <!-- {{ seomaticMeta.canonicalUrl }} (defaults to craft.request.url) -->
<meta name="geo.region" content="NY" /> <!-- {{ seomaticIdentity.address.addressRegion }} -->
<meta name="geo.position" content="41.005432,-73.65897799999999" /> <!-- {{ seomaticIdentity.location.geo.latitude }},{{ seomaticIdentity.location.geo.longitude }} -->
<meta name="ICBM" content="41.005432,-73.65897799999999" /> <!-- {{ seomaticIdentity.location.geo.latitude }},{{ seomaticIdentity.location.geo.longitude }} -->
<meta name="geo.placename" content="Big Entity, Inc." /> <!-- {{ seomaticIdentity.location.name }} -->
<!-- Dublin Core basic info -->
<meta name="dcterms.Identifier" content="http://nystudio107.dev/" /> <!-- {{ seomaticMeta.canonicalUrl }} (defaults to craft.request.url) -->
<meta name="dcterms.Format" content="text/html" /> <!-- text/html -->
<meta name="dcterms.Relation" content="Big Entity, Inc." /> <!-- {{ seomaticSiteMeta.siteSeoName }} -->
<meta name="dcterms.Language" content="en" /> <!-- {{ craft.locale }} -->
<meta name="dcterms.Publisher" content="Big Entity, Inc." /> <!-- {{ seomaticSiteMeta.siteSeoName }} -->
<meta name="dcterms.Type" content="text/html" /> <!-- text/html -->
<meta name="dcterms.Coverage" content="http://nystudio107.dev/" /> <!-- {{ siteUrl }} -->
<meta name="dcterms.Rights" content="Copyright ©2016 Big Entity, Inc. " /> <!-- {{ seomaticHelper.ownerCopyrightNotice }} -->
<meta name="dcterms.Title" content="We make the big stuff big & the little stuff…" /> <!-- {{ seomaticMeta.seoTitle }} -->
<meta name="dcterms.Creator" content="nystudio107" /> <!-- {{ seomaticCreator.name }} -->
<meta name="dcterms.Subject" content="colossal, considerable, enormous, fat, full, gigantic, hefty, huge, immense, massive, sizable, substantial, tremendous" /> <!-- {{ seomaticMeta.seoKeywords }} -->
<meta name="dcterms.Contributor" content="Big Entity, Inc." /> <!-- {{ seomaticSiteMeta.siteSeoName }} -->
<meta name="dcterms.Date" content="2016-02-07" /> <!-- {{ now | date('Y-m-d') }} -->
<meta name="dcterms.Description" content="Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!" /> <!-- {{ seomaticMeta.seoDescription }} -->
<!-- Facebook OpenGraph -->
<meta property="fb:profile_id" content="bigentity" /> <!-- {{ seomaticSocial.facebookProfileId }} -->
<meta property="og:type" content="website" /> <!-- {{ seomatic.og.type }} -->
<meta property="og:locale" content="en_US" /> <!-- {{ seomatic.og.locale }} -->
<meta property="og:url" content="http://nystudio107.dev/" /> <!-- {{ seomatic.og.url }} -->
<meta property="og:title" content="We make the big stuff big & the little stuff little | Big Entity, Inc." /> <!-- {{ seomatic.og.title }} -->
<meta property="og:description" content="Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!" /> <!-- {{ seomatic.og.description }} -->
<meta property="og:image" content="http://nystudio107.dev/img/site/big_hq.jpg" /> <!-- {{ seomatic.og.image }} -->
<meta property="og:site_name" content="Big Entity, Inc." /> <!-- {{ seomatic.og.site_name }} -->
<meta property="og:see_also" content="https://twitter.com/bigentity" /> <!-- {{ seomatic.og.see_also[0] }} -->
<meta property="og:see_also" content="https://www.facebook.com/bigentity" /> <!-- {{ seomatic.og.see_also[1] }} -->
<meta property="og:see_also" content="https://plus.google.com/+bigentity" /> <!-- {{ seomatic.og.see_also[2] }} -->
<meta property="og:see_also" content="https://www.linkedin.com/company/bigentity" /> <!-- {{ seomatic.og.see_also[3] }} -->
<meta property="og:see_also" content="https://www.youtube.com/user/bigentity" /> <!-- {{ seomatic.og.see_also[4] }} -->
<meta property="og:see_also" content="https://www.youtube.com/c/bigentity" /> <!-- {{ seomatic.og.see_also[5] }} -->
<meta property="og:see_also" content="https://www.instagram.com/bigentity" /> <!-- {{ seomatic.og.see_also[6] }} -->
<meta property="og:see_also" content="https://www.pinterest.com/bigentity" /> <!-- {{ seomatic.og.see_also[7] }} -->
<meta property="og:see_also" content="https://github.com/bigentity" /> <!-- {{ seomatic.og.see_also[8] }} -->
<!-- Twitter Card -->
<meta property="twitter:card" content="summary" /> <!-- {{ seomatic.twitter.card }} -->
<meta property="twitter:site" content="@bigentity" /> <!-- {{ seomatic.twitter.site }} -->
<meta property="twitter:title" content="We make the big stuff big & the little stuff little | Big Entity, Inc." /> <!-- {{ seomatic.twitter.title }} -->
<meta property="twitter:description" content="Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!" /> <!-- {{ seomatic.twitter.description }} -->
<meta property="twitter:image" content="http://nystudio107.dev/img/site/big_hq.jpg" /> <!-- {{ seomatic.twitter.image }} -->
<!-- Google Publisher -->
<link rel="publisher" href="https://plus.google.com/+bigentity" /> <!-- {{ seomaticHelper.googlePlusUrl }} -->
<!-- Humans.txt authorship http://humanstxt.org -->
<link type="text/plain" rel="author" href="/humans.txt" />
<!-- Domain verification -->
<meta name="google-site-verification" content="BM6VkEojTIASDEWyTLro7VNhZnW_036LNdcYk5j9X_8g" /> <!-- {{ seomaticHelper.ownerGoogleSiteVerification }} -->
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXX-XX', 'auto');
ga('require', 'displayfeatures');
ga('send', 'pageview');
</script>
<!-- END SEOmatic rendered SEO Meta -->
#### Rendered Identity Microdata
The `{% hook 'seomaticRender' %}` tag also generates [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) identity microdata that tells search engines about the company that owns the website. JSON-LD is an alternative to microdata you may already be familiar with, such as: `<div itemscope itemtype='http://schema.org/Organization'>`. JSON-LD has the advantage of not being intertwined with HTML markup, so it's easier to use. It is parsed and consumed by Google, allowing you to tell Google what your site is about, rather than having it try to guess.
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "AdultEntertainment",
"name": "Big Entity, Inc.",
"alternateName": "Big",
"description": "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
"url": "http://BigEntity.com",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"image": "http://nystudio107.dev/img/site/big_logo.jpg",
"telephone": "585.325.1910",
"email": "info@ BigEntity.com",
"address": {
"@type": "PostalAddress",
"streetAddress": "311 N Main St",
"addressLocality": "Portchester",
"addressRegion": "NY",
"postalCode": "10573",
"addressCountry": "US"
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Monday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Tuesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Wednesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Thursday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Friday"],
"opens": "12:00:00"
}
],
"logo": "http://nystudio107.dev/img/site/big_logo.jpg",
"location": {
"@type": "Place",
"name": "Big Entity, Inc.",
"alternateName": "Big",
"description": "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
"hasMap": "http://maps.google.com/maps?q=Big+Entity%2C+Inc.%2C+311+N+Main+St%2C+Portchester%2C+NY+10573%2C+US",
"telephone": "585.325.1910",
"image": "http://nystudio107.dev/img/site/big_logo.jpg",
"logo": "http://nystudio107.dev/img/site/big_logo.jpg",
"url": "http://BigEntity.com",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Monday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Tuesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Wednesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Thursday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Friday"],
"opens": "12:00:00"
}
],
"geo": {
"@type": "GeoCoordinates",
"latitude": "41.005432",
"longitude": "-73.65897799999999"
},
"address": {
"@type": "PostalAddress",
"streetAddress": "311 N Main St",
"addressLocality": "Portchester",
"addressRegion": "NY",
"postalCode": "10573",
"addressCountry": "US"
}
},
"duns": "54316",
"founder": "Mr. Big",
"foundingDate": "2011-11-01",
"foundingLocation": "Redding, CT, USA"
}
</script>
#### Rendered WebSite Microdata
The `{% hook 'seomaticRender' %}` tag also generates [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) WebSite microdata that tells search engines about the website. JSON-LD is an alternative to microdata you may already be familiar with, such as: `<div itemscope itemtype='http://schema.org/Organization'>`. JSON-LD has the advantage of not being intertwined with HTML markup, so it's easier to use. It is parsed and consumed by Google, allowing you to tell Google what your site is about, rather than having it try to guess.
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebSite",
"name": "Big Entity, Inc.",
"description": "Big Entity specializes in making the big stuff big, but we also know how to make the little stuff little!",
"url": "http://nystudio107.dev/",
"image": "http://nystudio107.dev/img/site/big_hq.jpg",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"copyrightHolder": {
"@type": "AdultEntertainment",
"name": "Big Entity, Inc.",
"alternateName": "Big",
"description": "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
"url": "http://BigEntity.com",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"image": "http://nystudio107.dev/img/site/big_logo.jpg",
"telephone": "585.325.1910",
"email": "info@ BigEntity.com",
"address": {
"@type": "PostalAddress",
"streetAddress": "311 N Main St",
"addressLocality": "Portchester",
"addressRegion": "NY",
"postalCode": "10573",
"addressCountry": "US"
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Monday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Tuesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Wednesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Thursday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Friday"],
"opens": "12:00:00"
}
],
"logo": "http://nystudio107.dev/img/site/big_logo.jpg",
"location": {
"@type": "Place",
"name": "Big Entity, Inc.",
"alternateName": "Big",
"description": "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
"hasMap": "http://maps.google.com/maps?q=Big+Entity%2C+Inc.%2C+311+N+Main+St%2C+Portchester%2C+NY+10573%2C+US",
"telephone": "585.325.1910",
"image": "http://nystudio107.dev/img/site/big_logo.jpg",
"logo": "http://nystudio107.dev/img/site/big_logo.jpg",
"url": "http://BigEntity.com",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Monday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Tuesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Wednesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Thursday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Friday"],
"opens": "12:00:00"
}
],
"geo": {
"@type": "GeoCoordinates",
"latitude": "41.005432",
"longitude": "-73.65897799999999"
},
"address": {
"@type": "PostalAddress",
"streetAddress": "311 N Main St",
"addressLocality": "Portchester",
"addressRegion": "NY",
"postalCode": "10573",
"addressCountry": "US"
}
},
"duns": "54316",
"founder": "Mr. Big",
"foundingDate": "2011-11-01",
"foundingLocation": "Redding, CT, USA"
},
"author": {
"@type": "AdultEntertainment",
"name": "Big Entity, Inc.",
"alternateName": "Big",
"description": "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
"url": "http://BigEntity.com",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"image": "http://nystudio107.dev/img/site/big_logo.jpg",
"telephone": "585.325.1910",
"email": "info@ BigEntity.com",
"address": {
"@type": "PostalAddress",
"streetAddress": "311 N Main St",
"addressLocality": "Portchester",
"addressRegion": "NY",
"postalCode": "10573",
"addressCountry": "US"
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Monday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Tuesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Wednesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Thursday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Friday"],
"opens": "12:00:00"
}
],
"logo": "http://nystudio107.dev/img/site/big_logo.jpg",
"location": {
"@type": "Place",
"name": "Big Entity, Inc.",
"alternateName": "Big",
"description": "We sell only big stuff... but we'll sell you little stuff too, but only in bulk containers of 1,000 units per container. So then it's big too.",
"hasMap": "http://maps.google.com/maps?q=Big+Entity%2C+Inc.%2C+311+N+Main+St%2C+Portchester%2C+NY+10573%2C+US",
"telephone": "585.325.1910",
"image": "http://nystudio107.dev/img/site/big_logo.jpg",
"logo": "http://nystudio107.dev/img/site/big_logo.jpg",
"url": "http://BigEntity.com",
"sameAs": ["https://twitter.com/bigentity","https://www.facebook.com/bigentity","https://plus.google.com/+bigentity","https://www.linkedin.com/company/bigentity","https://www.youtube.com/user/bigentity","https://www.youtube.com/c/bigentity","https://www.instagram.com/bigentity","https://www.pinterest.com/bigentity","https://github.com/bigentity"],
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Monday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Tuesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Wednesday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "22:00:00",
"dayOfWeek": ["Thursday"],
"opens": "12:00:00"
},
{
"@type": "OpeningHoursSpecification",
"closes": "20:00:00",
"dayOfWeek": ["Friday"],
"opens": "12:00:00"
}
],
"geo": {
"@type": "GeoCoordinates",
"latitude": "41.005432",
"longitude": "-73.65897799999999"
},
"address": {
"@type": "PostalAddress",
"streetAddress": "311 N Main St",
"addressLocality": "Portchester",
"addressRegion": "NY",
"postalCode": "10573",
"addressCountry": "US"
}
},
"duns": "54316",
"founder": "Mr. Big",
"foundingDate": "2011-11-01",
"foundingLocation": "Redding, CT, USA"
},
"creator": {
"@type": "Corporation",
"name": "nystudio107",
"alternateName": "NY Studio 107",
"description": "We do consulting, branding, design, and development. Impeccable design married with precision engineering.",
"url": "http://nystudio107.com",
"image": "http://nystudio107.dev/img/site/logo.png",
"telephone": "585.555.1212",
"email": "info@nystudio107.com",
"address": {
"@type": "PostalAddress",
"addressLocality": "Webster",
"addressRegion": "NY",
"postalCode": "14580",
"addressCountry": "US"
},
"logo": "http://nystudio107.dev/img/site/logo.png",
"location": {
"@type": "Place",
"name": "nystudio107",
"alternateName": "NY Studio 107",
"description": "We do consulting, branding, design, and development. Impeccable design married with precision engineering.",
"telephone": "585.555.1212",
"url": "http://nystudio107.com",
"address": {
"@type": "PostalAddress",
"addressLocality": "Webster",
"addressRegion": "NY",
"postalCode": "14580",
"addressCountry": "US"
}
},
"founder": "Andrew & Polly Welch",
"foundingDate": "2012-11-03"
}
}
</script>
#### Rendered Place Microdata
The `{% hook 'seomaticRender' %}` tag also generates [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) Place microdata for Organizations that tells search engines where the organization is located. JSON-LD is an alternative to microdata you may already be familiar with, such as: `<div itemscope itemtype='http://schema.org/Organization'>`. JSON-LD has the advantage of not being intertwined with HTML markup, so it's easier to use. It is parsed and consumed by Google, allowing you to tell Google what your site is about, rather than having it try to guess.
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Place",
"name": "Brad Brands Intl.",
"alternateName": "Brad's pits",
"description": "We make the products that make the man",
"hasMap": "http://maps.google.com/maps?q=Brad+Brands+Intl.%2C+123+Musky+Way%2C+Pittsville%2C+NY+12340%2C+US",
"image": "http://bradsformen.dev/img/site/site_logo@2x.png",
"logo": "http://bradsformen.dev/img/site/site_logo@2x.png",
"url": "http://bradsformen.com/",
"sameAs": ["https://twitter.com/bradsformen","https://www.facebook.com/bradsformen","https://plus.google.com/+bradsformen","https://www.linkedin.com/company/bradsformen","https://www.youtube.com/user/bradsformen","https://www.instagram.com/bradsformen","https://www.pinterest.com/bradsformen"],
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Musky Way",
"addressLocality": "Pittsville",
"addressRegion": "NY",
"postalCode": "12340",
"addressCountry": "US"
}
}
</script>
#### Rendered Product Microdata
The `{% hook 'seomaticRender' %}` tag also generates [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) Product microdata if an SEOmatic FieldType is attached to a Craft Commerce Product. JSON-LD is an alternative to microdata you may already be familiar with, such as: `<div itemscope itemtype='http://schema.org/Organization'>`. JSON-LD has the advantage of not being intertwined with HTML markup, so it's easier to use. It is parsed and consumed by Google, allowing you to tell Google what your site is about, rather than having it try to guess.
<script type="application/ld+json">
[
{
"@context": "http://schema.org",
"@type": "Product",
"name": "Romper for a Red Eye",
"description": "Irresistible to women. Establishes dominance over men. Brad's for Men will release your inner beast with its musky essence.",
"image": "http://bradsformen.dev/img/site/site_logo.png",
"logo": "http://bradsformen.dev/img/site/site_logo.png",
"url": "http://bradsformen.dev/commerce/products/romper-for-a-red-eye",
"sku": "Romper for a Red Eye",
"offers": {
"@type": "Offer",
"url": "http://bradsformen.dev/commerce/products/romper-for-a-red-eye",
"price": "30.00",
"priceCurrency": "USD",
"offeredBy": {
"@type": "Corporation",
"name": "Brad Brands Intl.",
"alternateName": "Brad's pits",
"description": "We make the products that make the man",
"url": "http://bradsformen.com/",
"sameAs": ["https://twitter.com/bradsformen","https://www.facebook.com/bradsformen","https://plus.google.com/+bradsformen","https://www.linkedin.com/company/bradsformen","https://www.youtube.com/user/bradsformen","https://www.instagram.com/bradsformen","https://www.pinterest.com/bradsformen"],
"image": "http://bradsformen.dev/img/site/site_logo@2x.png",
"email": "info@bradsformen.com",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Musky Way",
"addressLocality": "Pittsville",
"addressRegion": "NY",
"postalCode": "12340",
"addressCountry": "US"
},
"logo": "http://bradsformen.dev/img/site/site_logo@2x.png",
"location": {
"@type": "Place",
"name": "Brad Brands Intl.",
"alternateName": "Brad's pits",
"description": "We make the products that make the man",
"hasMap": "http://maps.google.com/maps?q=Brad+Brands+Intl.%2C+123+Musky+Way%2C+Pittsville%2C+NY+12340%2C+US",
"image": "http://bradsformen.dev/img/site/site_logo@2x.png",
"logo": "http://bradsformen.dev/img/site/site_logo@2x.png",
"url": "http://bradsformen.com/",
"sameAs": ["https://twitter.com/bradsformen","https://www.facebook.com/bradsformen","https://plus.google.com/+bradsformen","https://www.linkedin.com/company/bradsformen","https://www.youtube.com/user/bradsformen","https://www.instagram.com/bradsformen","https://www.pinterest.com/bradsformen"],
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Musky Way",
"addressLocality": "Pittsville",
"addressRegion": "NY",
"postalCode": "12340",
"addressCountry": "US"
}
},
"duns": "12435",
"founder": "Brad Bell",
"foundingDate": "12/2015",
"foundingLocation": "Pittsville, NY, USA"
},
"seller": {
"@type": "Corporation",
"name": "Brad Brands Intl.",
"alternateName": "Brad's pits",
"description": "We make the products that make the man",
"url": "http://bradsformen.com/",
"sameAs": ["https://twitter.com/bradsformen","https://www.facebook.com/bradsformen","https://plus.google.com/+bradsformen","https://www.linkedin.com/company/bradsformen","https://www.youtube.com/user/bradsformen","https://www.instagram.com/bradsformen","https://www.pinterest.com/bradsformen"],
"image": "http://bradsformen.dev/img/site/site_logo@2x.png",
"email": "info@bradsformen.com",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Musky Way",
"addressLocality": "Pittsville",
"addressRegion": "NY",
"postalCode": "12340",
"addressCountry": "US"
},
"logo": "http://bradsformen.dev/img/site/site_logo@2x.png",
"location": {
"@type": "Place",
"name": "Brad Brands Intl.",
"alternateName": "Brad's pits",
"description": "We make the products that make the man",
"hasMap": "http://maps.google.com/maps?q=Brad+Brands+Intl.%2C+123+Musky+Way%2C+Pittsville%2C+NY+12340%2C+US",
"image": "http://bradsformen.dev/img/site/site_logo@2x.png",
"logo": "http://bradsformen.dev/img/site/site_logo@2x.png",
"url": "http://bradsformen.com/",
"sameAs": ["https://twitter.com/bradsformen","https://www.facebook.com/bradsformen","https://plus.google.com/+bradsformen","https://www.linkedin.com/company/bradsformen","https://www.youtube.com/user/bradsformen","https://www.instagram.com/bradsformen","https://www.pinterest.com/bradsformen"],
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Musky Way",
"addressLocality": "Pittsville",
"addressRegion": "NY",
"postalCode": "12340",
"addressCountry": "US"
}
},
"duns": "12435",
"founder": "Brad Bell",
"foundingDate": "12/2015",
"foundingLocation": "Pittsville, NY, USA"
}
}
}
]
</script>
If you click on the **Preview SEO Meta Tags** button when you are editing a SEO Template Meta, you'll see that particular template's SEO Template Meta tags. Otherwise, you will see the SEO Site Meta tags.
## Testing Your SEO Meta
Use Google's [Structured Data Testing Tool](https://developers.google.com/structured-data/testing-tool/) to view your metadata/microdata as Google sees it, and validate it for accuracy.
Use Facebook's [Open Graph Debugger](https://developers.facebook.com/tools/debug) to validate and verify your Open Graph meta tags.
Use Twitter's [Twitter Card Validator](https://cards-dev.twitter.com/validator) to validate and verify your Twitter Cards.
================================================
FILE: LICENSE.txt
================================================
The SEOmatic License
Copyright (c) 2015 nystudio107
Permission is hereby granted, free of charge, to any person or entity obtaining a copy of this software and associated documentation files (the "Software"), to use the software in any capacity, including commercial and for-profit use. Permission is also granted to alter, modify, or extend the Software for your own use, or commission a third-party to perform modifications for you.
Permission is NOT granted to create derivative works, sublicense, and/or sell copies of the Software. This is not FOSS software.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
[](http://unmaintained.tech/)
# DEPRECATED
This Craft CMS 2.x plugin is no longer supported, but it is fully functional, and you may continue to use it as you see fit. The license also allows you to fork it and make changes as needed for legacy support reasons.
The Craft CMS 3.x version of this plugin can be found here: [craft-seomatic](https://github.com/nystudio107/craft-seomatic) and can also be installed via the Craft Plugin Store in the Craft CP.
# SEOmatic plugin for Craft
A turnkey SEO implementation for Craft CMS that is comprehensive, powerful, and flexible.

Related: [SEOmatic for Craft 3.x](https://github.com/nystudio107/craft-seomatic)
## Installation
To install SEOmatic, follow these steps:
1. Download & unzip the file and place the `seomatic` directory into your `craft/plugins` directory
2. -OR- do a `git clone https://github.com/nystudio107/seomatic.git` directly into your `craft/plugins` folder. You can then update it with `git pull`
3. -OR- install with Composer via `composer require nystudio107/seomatic`
4. Install plugin in the Craft Control Panel under Settings > Plugins
5. The plugin folder should be named `seomatic` for Craft to see it. GitHub recently started appending `-master` (the branch name) to the name of the folder for zip file downloads.
SEOmatic works on Craft 2.4.x, Craft 2.5.x, and Craft 2.6.x.
The SEOmetrics feature requires PHP 5.4 or later and that you have the [php-xml extension](http://osticket.com/forum/discussion/8702/php-fatal-error-call-to-undefined-function-utf8-encode-error-message) installed.
## Overview
Learn more about SEO: [Modern SEO: Snake Oil vs. Substance](https://nystudio107.com/blog/modern-seo-snake-oil-vs-substance)
Learn more about JSON-LD Structured Data: [JSON-LD, Structured Data and Erotica](https://nystudio107.com/blog/json-ld-structured-data-and-erotica)
### Video overview of SEOmatic:
[](https://www.youtube.com/watch?v=f1149YVEF_0)
SEOmatic allows you to quickly get a website up and running with a robust, comprehensive SEO strategy. It is also implemented in a Craft-y way, in that it is also flexible and customizable. The SEOmetrics feature scans your content for focus keywords, and offers analysis on how to improve your SEO.
It implements [JSON-LD](https://developers.google.com/schemas/formats/json-ld?hl=en) microdata, [Dublin Core](http://dublincore.org) core metadata, [Twitter Cards](https://dev.twitter.com/cards/overview) tags, [Facebook OpenGraph](https://developers.facebook.com/docs/sharing/opengraph) tags, [Humans.txt](http://humanstxt.org) authorship accreditation, and as well as HTML meta tags.
The general philosophy is that SEO Site Meta can be overridden by SEO Template Meta, which can be overridden by SEO Entry Meta, which can be overridden by dynamic SEO Twig tags.
In this way, the SEO Meta tags on your site cascade, so that they are globally available, but also can be customized in a very granular way.
SEOmatic populates your templates with SEO Meta in the same way that Craft populates your templates with `entry` variables, with a similar level of freedom and flexibility in terms of how you utilize them.
SEOmatic also caches each unique SEO Meta request so that your website performance is minimally impacted by the rich SEO Meta tags provided.
## Documentation
Please read the complete documentation in the [SEOmatic Wiki](https://github.com/nystudio107/seomatic/wiki) or read the `DOCS.md` file in the repo.
To better understand how all of this metadata benefits your website, please read: [Promote Your Content with Structured Data Markup](https://developers.google.com/structured-data/)
If you need to redirect from legacy URLs to preserve SEO value when rebuilding & restructuring a website, check out the [Retour Plugin](https://github.com/nystudio107/retour)
## Roadmap
Some things to do, and ideas for potential features:
* [bug] Get the Template Metas implemented with full `locale` support, so the settings can all be per-locale based
* [bug] Enforce *required fields on the various settings pages in the Admin CP by doing proper validation
* [bug] The `foundingDate` fields probably should be dateTimeField types on the Settings pages
* [feature] Provide SiteMap functionality. Yes, it's SEO-related, but seems like it might be better to keep SEOmatic focused (?)
* [feature] Allow people to choose individual fields to pull from inside of Matrix and Neo blocks
Brought to you by [nystudio107](http://nystudio107.com)
================================================
FILE: SeomaticPlugin.php
================================================
<?php
namespace Craft;
class SeomaticPlugin extends BasePlugin
{
public function getName()
{
$pluginNameOverride = $this->getSettings()->getAttribute('pluginNameOverride');
return empty($pluginNameOverride) ? Craft::t('SEOmatic') : $pluginNameOverride;
}
public function getDescription()
{
return 'A turnkey SEO implementation for Craft CMS that is comprehensive, powerful, and flexible.';
}
public function getDocumentationUrl()
{
return 'https://github.com/nystudio107/seomatic/wiki';
}
public function getReleaseFeedUrl()
{
return 'https://raw.githubusercontent.com/nystudio107/seomatic/master/releases.json';
}
public function getVersion()
{
return '1.1.56';
}
public function getSchemaVersion()
{
return '1.1.25';
}
public function getDeveloper()
{
return 'nystudio107';
}
public function getDeveloperUrl()
{
return 'https://nystudio107.com';
}
public function hasCpSection()
{
return true;
}
public function init()
{
require_once __DIR__ . '/vendor/autoload.php';
craft()->templates->hook('seomaticRender', function(&$context)
{
if ((craft()->request->isSiteRequest()) && (isset($context['seomaticMeta'])))
{
$locale = craft()->language;
$seomaticMeta = $context['seomaticMeta'];
$seomaticSiteMeta = $context['seomaticSiteMeta'];
$seomaticIdentity = $context['seomaticIdentity'];
$seomaticSocial = $context['seomaticSocial'];
$seomaticCreator = $context['seomaticCreator'];
$seomaticHelper = $context['seomaticHelper'];
$dataLayer = null;
if (!empty($context['dataLayer'])) {
$dataLayer = $context['dataLayer'];
}
/* -- We want to pass an up-to-date variable context to the template, so pass everything on in */
$result="";
$metaVars = array(
'seomaticMeta' => $seomaticMeta,
'seomaticSiteMeta' => $seomaticSiteMeta,
'seomaticIdentity' => $seomaticIdentity,
'seomaticSocial' => $seomaticSocial,
'seomaticCreator' => $seomaticCreator,
'seomaticHelper' => $seomaticHelper,
'dataLayer' => $dataLayer,
);
/* -- Main Entity of Page info, which is optional */
if (isset($context['seomaticMainEntityOfPage']))
$metaVars['seomaticMainEntityOfPage'] = $context['seomaticMainEntityOfPage'];
/* -- Render the seomaticMeta, this is where the magic happens */
$seomaticTemplatePath = '';
if (isset($context['seomaticTemplatePath']))
$seomaticTemplatePath = $context['seomaticTemplatePath'];
$result = craft()->seomatic->renderSiteMeta($seomaticTemplatePath, $metaVars, $locale);
return $result;
}
});
}
public function addTwigExtension()
{
Craft::import('plugins.seomatic.twigextensions.SeomaticTwigExtension');
return new SeomaticTwigExtension();
}
public function registerSiteRoutes()
{
return array(
'humans.txt' => array('action' => 'seomatic/renderHumans'),
'robots.txt' => array('action' => 'seomatic/renderRobots'),
);
}
public function registerCpRoutes()
{
return array(
'seomatic/site' => array('action' => 'seomatic/editSiteMeta'),
'seomatic/site/(?P<locale>[-\w\.*]+)' => array('action' => 'seomatic/editSiteMeta'),
'seomatic/identity' => array('action' => 'seomatic/editIdentity'),
'seomatic/identity/(?P<locale>[-\w\.*]+)' => array('action' => 'seomatic/editIdentity'),
'seomatic/social' => array('action' => 'seomatic/editSocial'),
'seomatic/social/(?P<locale>[-\w\.*]+)' => array('action' => 'seomatic/editSocial'),
'seomatic/creator' => array('action' => 'seomatic/editCreator'),
'seomatic/creator/(?P<locale>[-\w\.*]+)' => array('action' => 'seomatic/editCreator'),
'seomatic/meta/new' => array('action' => 'seomatic/editMeta'),
'seomatic/meta/new/(?P<locale>[-\w\.*]+)' => array('action' => 'seomatic/editMeta'),
'seomatic/meta/(?P<metaId>\d+)' => array('action' => 'seomatic/editMeta'),
'seomatic/meta/(?P<metaId>\d+)/(?P<locale>[-\w\.*]+)' => array('action' => 'seomatic/editMeta'),
'seomatic/settings' => array('action' => 'seomatic/editSettings'),
);
}
/**
* @return array
*/
protected function defineSettings()
{
return array(
'pluginNameOverride' => AttributeType::String
);
}
public function onAfterInstall()
{
/* -- Show our "Welcome to SEOmatic" message */
if (!craft()->isConsole())
craft()->request->redirect(UrlHelper::getCpUrl('seomatic/welcome'));
}
} /* -- class SeomaticPlugin */
================================================
FILE: composer.json
================================================
{
"name": "nystudio107/seomatic",
"minimum-stability": "dev",
"description": "A turnkey SEO implementation for Craft CMS that is comprehensive, powerful, and flexible",
"type": "craft-plugin",
"require": {
"crodas/text-rank" : "dev-master",
"davechild/textstatistics": "1.0.1",
"sunra/php-simple-html-dom-parser": "1.5.1",
"composer/installers": "~1.0"
}
}
================================================
FILE: config.php
================================================
<?php
/**
* SEOmatic Configuration
*
* Completely optional configuration settings for SEOmatic if you want to customize some
* of its more esoteric behavior, or just want specific control over things.
*
* Don't edit this file, instead copy it to 'craft/config' as 'seomatic.php' and make
* your changes there.
*/
return array(
/**
* The maximum number of characters allow for the seoTitle. It's HIGHLY recommend that
* you keep this set to 70 characters.
*/
"maxTitleLength" => 70,
/**
* Controls whether SEOmatic will truncate the text in <title> tags maxTitleLength characters.
* It is HIGHLY recommended that you leave this on, as search engines do not want
* <title> tags to be long, and long titles won't display well on mobile either.
*/
"truncateTitleTags" => true,
/**
* The maximum number of characters allow for the seoDescription. It's HIGHLY recommend that
* you keep this set to 160 characters.
*/
"maxDescriptionLength" => 160,
/**
* Controls whether SEOmatic will truncate the descrption tags maxDescriptionLength characters.
* It is HIGHLY recommended that you leave this on, as search engines do not want
* description tags to be long.
*/
"truncateDescriptionTags" => true,
/**
* The maximum number of characters allow for the seoKeywords. It's HIGHLY recommend that
* you keep this set to 200 characters.
*/
"maxKeywordsLength" => 200,
/**
* Controls whether SEOmatic will truncate the keywords tags maxKeywordsLength characters.
* It is HIGHLY recommended that you leave this on, as search engines do not want
* keywords tags to be long.
*/
"truncateKeywordsTags" => true,
/**
* SEOmatic will render the Google Analytics <script> tag and code for you, if you
* enter a Google Analytics UID tracking code in the Site Identity settings. It
* does not render the <script> tag if devMode is on or during Live Preview, but
* here is an additional override for controlling it.
*/
"renderGoogleAnalyticsScript" => true,
/**
* SEOmatic will render the Google Tag Manager <script> tag and code for you, if you
* enter a Google Tag Manager ID tracking code in the Site Identity settings. It
* does not render the <script> tag during Live Preview, but here is an additional
* override for controlling it. It does render the script tag if devMode is on,
* to allow for debugging GTM.
*/
"renderGoogleTagManagerScript" => true,
/**
* This controls the name of the Javascript variable that SEOmatic outputs for the
* dataLayer variable. Note that the Twig variable always will be named:
* `dataLayer` regardless of this setting.
*/
"gtmDataLayerVariableName" => "dataLayer",
/**
* SEOmatic will render Product JSON-LD microdata for you automatically, if an SEOmatic Meta
* FieldType is attached to a Craft Commerce Product. Set this to false to override
* this behavior, and not render the Product JSON-LD microdata.
*/
"renderCommerceProductJSONLD" => true,
/**
* SEOmatic uses the `siteUrl` to generate the external URLs. If you are using it in
* a non-standard environment, such as a headless ElementAPI server, you can override
* what it uses for the `siteUrl` below.
*/
"siteUrlOverride" => '',
/**
* Controls whether SEOmatic will display the SEOmetrics information during Live Preview.
*/
"displaySeoMetrics" => true,
/**
* Determines the name used for the "Home" default breadcrumb.
*/
"breadcrumbsHomeName" => 'Home',
/**
* Determines the string prepended to the <title> tag when devMode is on.
*/
"siteDevModeTitle" => '[devMode]',
/**
* This allows you to globally override the meta settings on your website. WARNING:
* anything you set here will REPLACE the meta settings globally. You might wish to
* use this, for instance, to set 'robots' to be 'none' on development/staging to
* prevent crawlers from indexing it. Since this config file is multi-environment aware,
* like any Craft config file, this allows you to do just that.
* Leave any value in the array blank to cause it to not override.
*/
"globalMetaOverride" => array(
'locale' => '',
'seoMainEntityCategory' => '',
'seoMainEntityOfPage' => '',
'seoTitle' => '',
'seoDescription' => '',
'seoKeywords' => '',
'seoImageTransform' => '',
'seoFacebookImageTransform' => '',
'seoTwitterImageTransform' => '',
'twitterCardType' => '',
'openGraphType' => '',
'robots' => '',
'seoImageId' => '',
),
/**
* This allows you to exclude locales from SEOmatic's automatic handling of
* hreflang. Useful for some multi-site situations
*/
"excludeLocales" => array(
),
);
================================================
FILE: controllers/SeomaticController.php
================================================
<?php
namespace Craft;
use \DaveChild\TextStatistics as TS;
use \Sunra\PhpSimple\HtmlDomParser;
class SeomaticController extends BaseController
{
protected $allowAnonymous = array('actionRenderHumans', 'actionRenderRobots', 'actionRenderMetrics');
protected $parsingDom = false;
/**
*/
public function actionEditSettings()
{
$seomaticPlugin = craft()->plugins->getPlugin('seomatic');
$settings = $seomaticPlugin->getSettings();
$this->renderTemplate('seomatic/settings', array(
'settings' => $settings
));
} /* -- actionEditSettings */
/* --------------------------------------------------------------------------------
Render the SEO Metrics
-------------------------------------------------------------------------------- */
public function actionRenderMetrics()
{
if (!$this->parsingDom)
{
$this->parsingDom = true;
$oldPath = method_exists(craft()->templates, 'getTemplatesPath') ? craft()->templates->getTemplatesPath() : craft()->path->getTemplatesPath();
$newPath = craft()->path->getPluginsPath().'seomatic/templates';
method_exists(craft()->templates, 'setTemplatesPath') ? craft()->templates->setTemplatesPath($newPath) : craft()->path->setTemplatesPath($newPath);
/* -- Render the SEOmatic display preview template */
$url = urldecode(craft()->request->getParam('url'));
if (UrlHelper::isAbsoluteUrl($url))
{
$urlParts = parse_url($url);
if (isset($urlParts['scheme']))
$rootUrl = $urlParts['scheme'] . "://" . $urlParts['host'];
else
$rootUrl = "http" . "://" . $urlParts['host'];
if (isset($urlParts['port']))
$rootUrl .= $urlParts['port'] . "/";
else
$rootUrl .= "/";
$keywordsParam = urldecode(craft()->request->getParam('keywords'));
$keywordsKeys = explode(",", $keywordsParam);
$keywords = array();
/* -- Silly work-around for what appears to be a file_get_contents bug with https -> http://stackoverflow.com/questions/10524748/why-im-getting-500-error-when-using-file-get-contents-but-works-in-a-browser */
$opts = array(
'ssl'=>array(
'verify_peer'=>false,
'verify_peer_name'=>false,
),
'http'=>array(
'ignore_errors' => true,
'header' => "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13\r\n"
)
);
$context = stream_context_create($opts);
$dom = HtmlDomParser::file_get_html($url, false, $context);
if ($dom)
{
$textStatistics = new TS\TextStatistics;
/* -- See if robots.txt exists */
$hasRobotsTxt = false;
$hasSitemap = false;
$sitemapUrl = rtrim($rootUrl, '/') . "/sitemap.xml";
$foundSitemapUrl = "";
$robotsUrl = rtrim($rootUrl, '/') . "/robots.txt";
$robots = @file_get_contents($robotsUrl, false, $context);
if ($robots !== false)
{
$hasRobotsTxt = true;
$lines = explode("\n", $robots);
foreach ($lines as $line)
{
$line = ltrim($line);
$searchStr = 'Sitemap';
$pos = strpos($line, $searchStr);
if ($pos !== false)
{
$pos += strlen($searchStr);
$foundSitemapUrl = substr($line, $pos);
$foundSitemapUrl = trim($sitemapUrl, ':');
$foundSitemapUrl = trim($sitemapUrl);
}
}
}
/* -- Check to see if a sitemap exists */
if ($foundSitemapUrl)
{
$siteMapContents = "";
$siteMapContents = @file_get_contents($sitemapUrl, false, $context, 0, 1);
if ($siteMapContents !== false)
$hasSitemap = true;
}
$siteMapContents = "";
$siteMapContents = @file_get_contents($sitemapUrl, false, $context, 0, 1);
if ($siteMapContents !== false)
$hasSitemap = true;
/* -- See if the site is https */
$sslReturnCode = 0;
$sslUrl = "https" . "://" . $urlParts['host'];
if (isset($urlParts['port']))
$sslUrl .= $sslUrl['port'] . '/';
else
$sslUrl .= '/';
$ch = curl_init($sslUrl);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$open_basedir = ini_get('open_basedir');
if (empty($open_basedir))
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_exec($ch);
$sslReturnCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
/* -- Check to see if the page is valid */
$validatorUrl = "https://validator.w3.org/check?uri=" . urlencode($url) . "&output=json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $validatorUrl);
$validatorResult = curl_exec($ch);
curl_close($ch);
$validatorStatus = $validatorErrors = $validatorWarnings = "";
if ($validatorResult)
{
$searchStr = "X-W3C-Validator-Status: ";
$pos = strpos($validatorResult, $searchStr);
if ($pos !== false)
{
$pos += strlen($searchStr);
$validatorStatus = substr($validatorResult, $pos, ( strpos($validatorResult, PHP_EOL, $pos) ) - $pos);
}
$searchStr = "X-W3C-Validator-Errors: ";
$pos = strpos($validatorResult, $searchStr);
if ($pos !== false)
{
$pos += strlen($searchStr);
$validatorErrors = substr($validatorResult, $pos, ( strpos($validatorResult, PHP_EOL, $pos) ) - $pos);
}
$searchStr = "X-W3C-Validator-Warnings: ";
$pos = strpos($validatorResult, $searchStr);
if ($pos !== false)
{
$pos += strlen($searchStr);
$validatorWarnings = substr($validatorResult, $pos, ( strpos($validatorResult, PHP_EOL, $pos) ) - $pos);
}
}
$validatorUrl = "https://validator.w3.org/check?uri=" . urlencode($url);
/* -- Check Google Pagespeed insights for desktop */
$pagespeedDesktopScore = "";
$pagespeedDesktopUrl = "https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url=" . urlencode($url) . "&strategy=desktop";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $pagespeedDesktopUrl);
$pagespeedDesktopResult = curl_exec($ch);
curl_close($ch);
$pageSpeedPageStats = array();
if ($pagespeedDesktopResult)
{
$pagespeedJson = json_decode($pagespeedDesktopResult, true);
if ($pagespeedJson)
{
if (!empty($pagespeedJson['pageStats']))
{
$pageSpeedPageStats = $pagespeedJson['pageStats'];
if (empty($pageSpeedPageStats['htmlResponseBytes']))
$pageSpeedPageStats['htmlResponseBytes'] = 0;
if (empty($pageSpeedPageStats['cssResponseBytes']))
$pageSpeedPageStats['cssResponseBytes'] = 0;
if (empty($pageSpeedPageStats['imageResponseBytes']))
$pageSpeedPageStats['imageResponseBytes'] = 0;
if (empty($pageSpeedPageStats['javascriptResponseBytes']))
$pageSpeedPageStats['javascriptResponseBytes'] = 0;
if (empty($pageSpeedPageStats['otherResponseBytes']))
$pageSpeedPageStats['otherResponseBytes'] = 0;
$pageSpeedPageStats['totalResponseBytes'] = $pageSpeedPageStats['htmlResponseBytes'] +
$pageSpeedPageStats['cssResponseBytes'] +
$pageSpeedPageStats['imageResponseBytes'] +
$pageSpeedPageStats['javascriptResponseBytes'] +
$pageSpeedPageStats['otherResponseBytes'];
}
if (isset($pagespeedJson['responseCode']) && ($pagespeedJson['responseCode'] == "200" || $pagespeedJson['responseCode'] == "301" || $pagespeedJson['responseCode'] == "302"))
{
if (isset($pagespeedJson['ruleGroups']['SPEED']['score']))
$pagespeedDesktopScore = intval($pagespeedJson['ruleGroups']['SPEED']['score']);
}
}
}
$pagespeedDesktopUrl = "https://developers.google.com/speed/pagespeed/insights/?url=" . urlencode($url) . "&tab=desktop";
/* -- Check Google Pagespeed insights for desktop */
$pagespeedMobileScore = "";
$pagespeedMobileUsability = "";
$pagespeedMobileUrl = "https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url=" . urlencode($url) . "&strategy=mobile";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($ch, CURLOPT_URL, $pagespeedMobileUrl);
$pagespeedMobileResult = curl_exec($ch);
curl_close($ch);
if ($pagespeedMobileResult)
{
$pagespeedJson = json_decode($pagespeedMobileResult, true);
if ($pagespeedJson)
{
if (isset($pagespeedJson['responseCode']) && ($pagespeedJson['responseCode'] == "200" || $pagespeedJson['responseCode'] == "301" || $pagespeedJson['responseCode'] == "302"))
{
if (isset($pagespeedJson['ruleGroups']['SPEED']['score']))
$pagespeedMobileScore = intval($pagespeedJson['ruleGroups']['SPEED']['score']);
if (isset($pagespeedJson['ruleGroups']['USABILITY']['score']))
$pagespeedMobileUsability = intval($pagespeedJson['ruleGroups']['USABILITY']['score']);
}
}
}
$pagespeedMobileUrl = "https://developers.google.com/speed/pagespeed/insights/?url=" . urlencode($url) . "&tab=mobile";
/* -- Scrape for JSON-LD before we remove the <script> tags */
$jsonLdTypes = array();
foreach($dom->find('script[type=application/ld+json]') as $elem)
{
$jsonArray = json_decode($elem->innertext, true);
if (isset($jsonArray['@type']))
array_push($jsonLdTypes, $jsonArray['@type']);
}
$jsonLdTypes = array_unique($jsonLdTypes);
/* -- Remove inline <script> and <style> tags, and then strip the DOM down */
foreach($dom->find('style') as $element)
$element->outertext = '';
foreach($dom->find('script') as $element)
$element->outertext = '';
$strippedDom = html_entity_decode($dom->plaintext);
// $strippedDom = preg_replace('@[^0-9a-z\.\!]+@i', ', ', $strippedDom);
$strippedDom = stripslashes($strippedDom);
$htmlDom = html_entity_decode($dom->outertext);
// $htmlDom = preg_replace('@[^0-9a-z\.\!]+@i', '', $htmlDom);
/* -- SEO statistics */
$titleTag = html_entity_decode($dom->find('title', 0)->plaintext);
$titleLength = strlen($titleTag);
$metaDescriptionTag = "";
$metaDescriptionLength = 0;
$elem = $dom->find('meta[name=description]', 0);
if ($elem)
{
$metaDescriptionTag = html_entity_decode($elem->content);
$metaDescriptionLength = strlen($metaDescriptionTag);
}
$metaTwitterTag = "";
$elem = $dom->find('meta[name=twitter:card],meta[property=twitter:card]', 0);
if ($elem)
$metaTwitterTag = html_entity_decode($elem->content);
$metaOpenGraphTag = "";
$elem = $dom->find('meta[property=og:type],meta[property=og:url],meta[property=og:title]', 0);
if ($elem)
$metaOpenGraphTag = html_entity_decode($elem->content);
$hasRelPublisherTag = false;
$elem = $dom->find('link[rel=publisher]', 0);
if ($elem)
$hasRelPublisherTag = true;
$emptyImageAlts = count($dom->find('img[!alt]'));
$h1Tags = count($dom->find('h1'));
$h2Tags = count($dom->find('h2'));
$h3Tags = count($dom->find('h3'));
$h4Tags = count($dom->find('h4'));
$h5Tags = count($dom->find('h5'));
$totalHTags = $h1Tags + $h2Tags + $h3Tags + $h4Tags + $h5Tags;
$effectiveHTags = true;
if ($h1Tags != 1)
$effectiveHTags = false;
if ($totalHTags < 3)
$effectiveHTags = false;
if ($h2Tags == 0 && ($h3Tags || $h4Tags || $h5Tags))
$effectiveHTags = false;
if ($h3Tags == 0 && ($h4Tags || $h5Tags))
$effectiveHTags = false;
if ($h4Tags == 0 && ($h5Tags))
$effectiveHTags = false;
$textToHtmlRatio = (strlen($strippedDom) / (strlen($htmlDom) - strlen($strippedDom))) * 100;
$strippedDom = preg_replace('/\s+/', ' ', $strippedDom);
/* -- Extract the page keywords, and clean them up a bit */
$pageKeywords = craft()->seomatic->extractKeywords($strippedDom);
$pageKeywords = str_replace(",,",",", $pageKeywords);
$pageKeywords = str_replace(" ,",",", $pageKeywords);
$pageKeywords = str_replace(" .",".", $pageKeywords);
$pageKeywords = preg_replace('/\.+/', '.', $pageKeywords);
$pageKeywords = preg_replace('/,+/', ',', $pageKeywords);
$pageKeywords = str_replace(",.,",",", $pageKeywords);
$pageKeywords = html_entity_decode($pageKeywords, ENT_COMPAT, 'UTF-8');
/* -- Focus keywords */
foreach ($keywordsKeys as $keywordsKey)
{
$keywordsKey = trim($keywordsKey);
if (strlen($keywordsKey))
{
$appearsInH1Tag = 0;
foreach($dom->find('h1') as $element)
$appearsInH1Tag += substr_count(strtolower($element->plaintext), strtolower($keywordsKey));
foreach($dom->find('h2') as $element)
$appearsInH1Tag += substr_count(strtolower($element->plaintext), strtolower($keywordsKey));
$appearsInImgTag = 0;
foreach($dom->find('img') as $element)
$appearsInImgTag += substr_count(strtolower($element->alt), strtolower($keywordsKey));
$appearsInAhrefTag = 0;
foreach($dom->find('a') as $element)
$appearsInAhrefTag += substr_count(strtolower($element->plaintext), strtolower($keywordsKey));
$keywords[$keywordsKey] = array(
'appearsInTitleTag' => substr_count(strtolower($titleTag), strtolower($keywordsKey)),
'appearsInUrl' => substr_count(strtolower($url), strtolower($keywordsKey)),
'appearsInMetaDescriptionTag' => substr_count(strtolower($metaDescriptionTag), strtolower($keywordsKey)),
'appearsInH1Tag' => $appearsInH1Tag,
'appearsInAhrefTag' => $appearsInAhrefTag,
'appearsInImgTag' => $appearsInImgTag,
'appearsInPageKeywords' => substr_count(strtolower($pageKeywords), strtolower($keywordsKey)),
'appearsOnWebPage' => substr_count(strtolower($strippedDom), strtolower($keywordsKey)),
);
}
}
/* -- Text statistics */
$wordCount = $textStatistics->wordCount($strippedDom);
$readingTime = floor($wordCount / 200);
if ($readingTime === 0)
$readingTime = 1;
$fleschKincaidReadingEase = $textStatistics->fleschKincaidReadingEase($strippedDom);
$fleschKincaidGradeLevel = $textStatistics->fleschKincaidGradeLevel($strippedDom);
$gunningFogScore = $textStatistics->gunningFogScore($strippedDom);
$colemanLiauIndex = $textStatistics->colemanLiauIndex($strippedDom);
$smogIndex = $textStatistics->smogIndex($strippedDom);
$automatedReadabilityIndex = $textStatistics->automatedReadabilityIndex($strippedDom);
$vars = array(
'titleTag' => $titleTag,
'titleLength' => $titleLength,
'metaDescriptionTag' => $metaDescriptionTag,
'metaDescriptionLength' => $metaDescriptionLength,
'metaTwitterTag' => $metaTwitterTag,
'metaOpenGraphTag' => $metaOpenGraphTag,
'hasRelPublisherTag' => $hasRelPublisherTag,
'jsonLdTypes' => $jsonLdTypes,
'hasRobotsTxt' => $hasRobotsTxt,
'hasSitemap' => $hasSitemap,
'emptyImageAlts' => $emptyImageAlts,
'validatorUrl' => $validatorUrl,
'validatorStatus' => $validatorStatus,
'validatorErrors' => $validatorErrors,
'validatorWarnings' => $validatorWarnings,
'pageSpeedPageStats' => $pageSpeedPageStats,
'pagespeedDesktopScore' => $pagespeedDesktopScore,
'pagespeedDesktopUrl' => $pagespeedDesktopUrl,
'pagespeedMobileScore' => $pagespeedMobileScore,
'pagespeedMobileUsability' => $pagespeedMobileUsability,
'pagespeedMobileUrl' => $pagespeedMobileUrl,
'sslReturnCode' => $sslReturnCode,
'h1Tags' => $h1Tags,
'h2Tags' => $h2Tags,
'h3Tags' => $h3Tags,
'h4Tags' => $h4Tags,
'h5Tags' => $h5Tags,
'effectiveHTags' => $effectiveHTags,
'textToHtmlRatio' => $textToHtmlRatio,
'wordCount' => $wordCount,
'readingTime' => $readingTime,
'pageKeywords' => $pageKeywords,
'keywords' => $keywords,
'fleschKincaidReadingEase' => $fleschKincaidReadingEase,
'fleschKincaidGradeLevel' => $fleschKincaidGradeLevel,
'gunningFogScore' => $gunningFogScore,
'colemanLiauIndex' => $colemanLiauIndex,
'smogIndex' => $smogIndex,
'automatedReadabilityIndex' => $automatedReadabilityIndex,
);
//$htmlText = craft()->templates->render('_seo_metrics.twig', $vars);
$this->renderTemplate('_seo_metrics.twig', $vars);
}
else
$this->renderTemplate('_error', array('errorMessage' => "Error parsing the DOM. Is this a valid, publicly accessible URL?"));
}
else
$this->renderTemplate('_error', array('errorMessage' => "Error loading the webpage. Is this a valid, publicly accessible URL?"));
method_exists(craft()->templates, 'setTemplatesPath') ? craft()->templates->setTemplatesPath($oldPath) : craft()->path->setTemplatesPath($oldPath);
}
$this->parsingDom = false;
} /* -- actionRenderMetrics */
/* --------------------------------------------------------------------------------
Render the humans.txt template
-------------------------------------------------------------------------------- */
public function actionRenderHumans(array $variables = array())
{
$templatePath = '';
$locale = '';
if (!$locale)
$locale = craft()->language;
$metaVars = craft()->seomatic->getGlobals('', $locale);
/* -- Tell Twig not to escape at all for this text template */
$twig = craft()->templates->getTwig();
$escaper = $twig->getExtension('escaper');
$escaper->setDefaultStrategy(false);
if ($templatePath)
{
$htmlText = craft()->templates->render($templatePath);
}
else
{
$oldPath = method_exists(craft()->templates, 'getTemplatesPath') ? craft()->templates->getTemplatesPath() : craft()->path->getTemplatesPath();
$newPath = craft()->path->getPluginsPath().'seomatic/templates';
method_exists(craft()->templates, 'setTemplatesPath') ? craft()->templates->setTemplatesPath($newPath) : craft()->path->setTemplatesPath($newPath);
/* -- Render the core template */
$templateName = '_humans';
$this->renderTemplate($templateName, $metaVars);
method_exists(craft()->templates, 'setTemplatesPath') ? craft()->templates->setTemplatesPath($oldPath) : craft()->path->setTemplatesPath($oldPath);
}
} /* -- actionRenderHumans */
/* --------------------------------------------------------------------------------
Render the robots.txt template
-------------------------------------------------------------------------------- */
public function actionRenderRobots(array $variables = array())
{
$templatePath = '';
$locale = '';
if (!$locale)
$locale = craft()->language;
$metaVars = craft()->seomatic->getGlobals('', $locale);
/* -- Tell Twig not to escape at all for this text template */
$twig = craft()->templates->getTwig();
$escaper = $twig->getExtension('escaper');
$escaper->setDefaultStrategy(false);
if ($templatePath)
{
$htmlText = craft()->templates->render($templatePath);
}
else
{
$oldPath = method_exists(craft()->templates, 'getTemplatesPath') ? craft()->templates->getTemplatesPath() : craft()->path->getTemplatesPath();
$newPath = craft()->path->getPluginsPath().'seomatic/templates';
method_exists(craft()->templates, 'setTemplatesPath') ? craft()->templates->setTemplatesPath($newPath) : craft()->path->setTemplatesPath($newPath);
/* -- Render the core template */
$templateName = '_robots';
$this->renderTemplate($templateName, $metaVars);
craft()->path->setTemplatesPath($oldPath);
method_exists(craft()->templates, 'setTemplatesPath') ? craft()->templates->setTemplatesPath($oldPath) : craft()->path->
gitextract_5t9rtuet/
├── .gitignore
├── CHANGELOG.md
├── DOCS.md
├── LICENSE.txt
├── README.md
├── SeomaticPlugin.php
├── composer.json
├── config.php
├── controllers/
│ └── SeomaticController.php
├── elementtypes/
│ └── Seomatic_MetaElementType.php
├── fieldtypes/
│ └── Seomatic_MetaFieldType.php
├── migrations/
│ ├── m151225_000000_seomatic_addHumansField.php
│ ├── m151226_000000_seomatic_addTwitterFacebookFields.php
│ ├── m160101_000000_seomatic_addRobotsFields.php
│ ├── m160111_000000_seomatic_addTitleFields.php
│ ├── m160122_000000_seomatic_addTypeFields.php
│ ├── m160123_000000_seomatic_addOpeningHours.php
│ ├── m160202_000000_seomatic_addSocialHandles.php
│ ├── m160204_000000_seomatic_addGoogleAnalytics.php
│ ├── m160205_000000_seomatic_addResturantMenu.php
│ ├── m160206_000000_seomatic_addGoogleAnalyticsPlugins.php
│ ├── m160206_000000_seomatic_addGoogleAnalyticsSendPageView.php
│ ├── m160209_000000_seomatic_alterDescriptionsColumns.php
│ ├── m160209_000001_seomatic_addRobotsTxt.php
│ ├── m160227_000000_seomatic_addFacebookAppId.php
│ ├── m160416_000000_seomatic_addContactPoints.php
│ ├── m160509_000000_seomatic_addSiteLinksBing.php
│ ├── m160707_000000_seomatic_addGoogleTagManager.php
│ ├── m160715_000000_seomatic_addSeoImageTransforms.php
│ ├── m160723_000000_seomatic_addSeoMainEntityOfPage.php
│ ├── m160724_000000_seomatic_addSeoMainEntityCategory.php
│ ├── m160811_000000_seomatic_addVimeo.php
│ ├── m160904_000000_seomatic_addTwitterFacebookImages.php
│ ├── m161220_000000_seomatic_addPriceRange.php
│ ├── m170212_000000_seomatic_addGoogleAnalyticsAnonymizeIp.php
│ └── m170212_000000_seomatic_addWikipedia.php
├── models/
│ ├── Seomatic_CreatorModel.php
│ ├── Seomatic_IdentityModel.php
│ ├── Seomatic_MetaFieldModel.php
│ ├── Seomatic_MetaModel.php
│ ├── Seomatic_SettingsModel.php
│ ├── Seomatic_SiteMetaModel.php
│ └── Seomatic_SocialModel.php
├── records/
│ ├── Seomatic_MetaRecord.php
│ └── Seomatic_SettingsRecord.php
├── releases.json
├── resources/
│ ├── css/
│ │ ├── bootstrap-tokenfield.css
│ │ ├── css-reset.css
│ │ ├── field.css
│ │ ├── seo-metrics-style.css
│ │ └── style.css
│ └── js/
│ ├── creator.js
│ ├── field.js
│ ├── field_settings.js
│ ├── identity.js
│ ├── main_entity_type_list.js
│ ├── meta.js
│ ├── metalist.js
│ ├── seomatic.js
│ ├── site.js
│ └── type_list.js
├── services/
│ └── SeomaticService.php
├── templates/
│ ├── _error.twig
│ ├── _facebookDisplayPreview.twig
│ ├── _googleAnalytics.twig
│ ├── _googleDisplayPreview.twig
│ ├── _googleTagManager.twig
│ ├── _humans.twig
│ ├── _humansDefault.twig
│ ├── _humansPreview.twig
│ ├── _preview_display_modal.twig
│ ├── _preview_humans_modal.twig
│ ├── _preview_robots_modal.twig
│ ├── _preview_tags_modal.twig
│ ├── _robots.twig
│ ├── _robotsDefault.twig
│ ├── _robotsPreview.twig
│ ├── _seo_meta.twig
│ ├── _seo_metaPreview.twig
│ ├── _seo_metrics.twig
│ ├── _seo_metrics_floater.twig
│ ├── _seomatic_tabs.twig
│ ├── _twitterCardDisplayPreview.twig
│ ├── creator/
│ │ └── _edit.twig
│ ├── field.twig
│ ├── field_settings.twig
│ ├── identity/
│ │ └── _edit.twig
│ ├── index.twig
│ ├── json-ld/
│ │ ├── _json-ld.twig
│ │ └── _json-ld_core.twig
│ ├── meta/
│ │ ├── _edit.twig
│ │ ├── _main.twig
│ │ ├── _sidebar.twig
│ │ └── index.twig
│ ├── seometrics.twig
│ ├── settings.twig
│ ├── site/
│ │ └── _edit.twig
│ ├── social/
│ │ └── _edit.twig
│ └── welcome.twig
├── translations/
│ ├── fr.php
│ └── nl.php
├── twigextensions/
│ └── SeomaticTwigExtension.php
├── variables/
│ └── SeomaticVariable.php
└── vendor/
├── autoload.php
├── composer/
│ ├── ClassLoader.php
│ ├── LICENSE
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_real.php
│ ├── autoload_static.php
│ └── installed.json
├── crodas/
│ └── text-rank/
│ ├── .travis.yml
│ ├── LICENSE
│ ├── README.md
│ ├── composer.json
│ ├── lib/
│ │ └── TextRank/
│ │ ├── Config.php
│ │ ├── DefaultEvents.php
│ │ ├── POS/
│ │ │ └── English/
│ │ │ ├── Tagger.php
│ │ │ ├── generate.php
│ │ │ ├── lexicon.php
│ │ │ └── lexicon.txt
│ │ ├── Stopword/
│ │ │ ├── Stopword.php
│ │ │ ├── czech-stopwords.txt
│ │ │ ├── danish-stopwords.txt
│ │ │ ├── dutch-stopwords.txt
│ │ │ ├── english-stopwords.txt
│ │ │ ├── finnish-stopwords.txt
│ │ │ ├── french-stopwords.txt
│ │ │ ├── generate.php
│ │ │ ├── german-stopwords.txt
│ │ │ ├── hungarian-stopwords.txt
│ │ │ ├── italian-stopwords.txt
│ │ │ ├── norwegian-stopwords.txt
│ │ │ ├── polish-stopwords.txt
│ │ │ ├── portuguese-stopwords.txt
│ │ │ ├── russian-stopwords.txt
│ │ │ ├── spanish-stopwords.txt
│ │ │ ├── swedish-stopwords.txt
│ │ │ └── turkish-stopwords.txt
│ │ ├── Stopword.php
│ │ ├── Summary.php
│ │ ├── SummaryPageRank.php
│ │ ├── TextRank.php
│ │ └── language-profile.php
│ ├── phpunit.xml
│ └── tests/
│ ├── QuickTest.php
│ ├── bootstrap.php
│ └── fixtures/
│ ├── english1.expected
│ ├── english1.summary
│ ├── english1.txt
│ ├── italian.expected
│ ├── italian.summary
│ ├── italian.txt
│ ├── spanish1.expected
│ ├── spanish1.summary
│ └── spanish1.txt
├── davechild/
│ └── textstatistics/
│ ├── .travis.yml
│ ├── LICENSE
│ ├── README.md
│ ├── composer.json
│ ├── phpunit.xml.dist
│ ├── src/
│ │ └── DaveChild/
│ │ └── TextStatistics/
│ │ ├── Maths.php
│ │ ├── Pluralise.php
│ │ ├── Resource.php
│ │ ├── Syllables.php
│ │ ├── Text.php
│ │ ├── TextStatistics.php
│ │ └── resources/
│ │ ├── DaleChallWordList.php
│ │ ├── Homographs.txt
│ │ └── SpacheWordList.php
│ └── tests/
│ ├── TextStatisticsCMULexTest.php
│ ├── TextStatisticsKiplingIfTest.php
│ ├── TextStatisticsMaths.php
│ ├── TextStatisticsMelvilleMobyDickTest.php
│ ├── TextStatisticsPluralise.php
│ └── TextStatisticsTest.php
└── sunra/
└── php-simple-html-dom-parser/
├── README.md
├── Src/
│ └── Sunra/
│ └── PhpSimple/
│ ├── HtmlDomParser.php
│ └── simplehtmldom_1_5/
│ ├── change_log.txt
│ └── simple_html_dom.php
└── composer.json
SYMBOL INDEX (556 symbols across 69 files)
FILE: SeomaticPlugin.php
class SeomaticPlugin (line 4) | class SeomaticPlugin extends BasePlugin
method getName (line 6) | public function getName()
method getDescription (line 12) | public function getDescription()
method getDocumentationUrl (line 17) | public function getDocumentationUrl()
method getReleaseFeedUrl (line 22) | public function getReleaseFeedUrl()
method getVersion (line 27) | public function getVersion()
method getSchemaVersion (line 32) | public function getSchemaVersion()
method getDeveloper (line 37) | public function getDeveloper()
method getDeveloperUrl (line 42) | public function getDeveloperUrl()
method hasCpSection (line 47) | public function hasCpSection()
method init (line 52) | public function init()
method addTwigExtension (line 101) | public function addTwigExtension()
method registerSiteRoutes (line 108) | public function registerSiteRoutes()
method registerCpRoutes (line 116) | public function registerCpRoutes()
method defineSettings (line 138) | protected function defineSettings()
method onAfterInstall (line 145) | public function onAfterInstall()
FILE: controllers/SeomaticController.php
class SeomaticController (line 7) | class SeomaticController extends BaseController
method actionEditSettings (line 15) | public function actionEditSettings()
method actionRenderMetrics (line 29) | public function actionRenderMetrics()
method actionRenderHumans (line 447) | public function actionRenderHumans(array $variables = array())
method actionRenderRobots (line 484) | public function actionRenderRobots(array $variables = array())
method actionEditSiteMeta (line 522) | public function actionEditSiteMeta(array $variables = array())
method actionEditIdentity (line 603) | public function actionEditIdentity(array $variables = array())
method actionEditSocial (line 649) | public function actionEditSocial(array $variables = array())
method actionEditCreator (line 669) | public function actionEditCreator(array $variables = array())
method actionEditMeta (line 719) | public function actionEditMeta(array $variables = array())
method actionSaveMeta (line 840) | public function actionSaveMeta()
method actionDeleteMeta (line 912) | public function actionDeleteMeta()
method actionSaveSiteMeta (line 937) | public function actionSaveSiteMeta()
method actionSaveIdentity (line 1005) | public function actionSaveIdentity()
method actionSaveSocial (line 1109) | public function actionSaveSocial()
method actionSaveCreator (line 1162) | public function actionSaveCreator()
FILE: elementtypes/Seomatic_MetaElementType.php
class Seomatic_MetaElementType (line 4) | class Seomatic_MetaElementType extends BaseElementType
method getName (line 7) | public function getName()
method hasContent (line 17) | public function hasContent()
method hasTitles (line 27) | public function hasTitles()
method hasStatuses (line 37) | public function hasStatuses()
method isLocalized (line 47) | public function isLocalized()
method getSources (line 58) | public function getSources($context = null)
method getAvailableActions (line 78) | public function getAvailableActions($source = null)
method defineTableAttributes (line 100) | public function defineTableAttributes($source = null)
method getTableAttributeHtml (line 115) | public function getTableAttributeHtml(BaseElementModel $element, $attr...
method defineCriteriaAttributes (line 142) | public function defineCriteriaAttributes()
method modifyElementsQuery (line 156) | public function modifyElementsQuery(DbCommand $query, ElementCriteriaM...
method populateElementModel (line 182) | public function populateElementModel($row)
FILE: fieldtypes/Seomatic_MetaFieldType.php
class Seomatic_MetaFieldType (line 7) | class Seomatic_MetaFieldType extends BaseFieldType
method getName (line 10) | public function getName()
method defineContentAttribute (line 15) | public function defineContentAttribute()
method getInputHtml (line 20) | public function getInputHtml($name, $value)
method defineSettings (line 208) | protected function defineSettings()
method getSettingsHtml (line 259) | public function getSettingsHtml()
method prepValueFromPost (line 330) | public function prepValueFromPost($value)
method prepValue (line 467) | public function prepValue($value)
method onAfterElementSave (line 521) | public function onAfterElementSave()
method getElementSources (line 560) | protected function getElementSources($elementType)
FILE: migrations/m151225_000000_seomatic_addHumansField.php
class m151225_000000_seomatic_addHumansField (line 7) | class m151225_000000_seomatic_addHumansField extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 27) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m151226_000000_seomatic_addTwitterFacebookFields.php
class m151226_000000_seomatic_addTwitterFacebookFields (line 7) | class m151226_000000_seomatic_addTwitterFacebookFields extends BaseMigra...
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 36) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160101_000000_seomatic_addRobotsFields.php
class m160101_000000_seomatic_addRobotsFields (line 7) | class m160101_000000_seomatic_addRobotsFields extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 34) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160111_000000_seomatic_addTitleFields.php
class m160111_000000_seomatic_addTitleFields (line 7) | class m160111_000000_seomatic_addTitleFields extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160122_000000_seomatic_addTypeFields.php
class m160122_000000_seomatic_addTypeFields (line 7) | class m160122_000000_seomatic_addTypeFields extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 36) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160123_000000_seomatic_addOpeningHours.php
class m160123_000000_seomatic_addOpeningHours (line 7) | class m160123_000000_seomatic_addOpeningHours extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 41) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160202_000000_seomatic_addSocialHandles.php
class m160202_000000_seomatic_addSocialHandles (line 7) | class m160202_000000_seomatic_addSocialHandles extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 34) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160204_000000_seomatic_addGoogleAnalytics.php
class m160204_000000_seomatic_addGoogleAnalytics (line 7) | class m160204_000000_seomatic_addGoogleAnalytics extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160205_000000_seomatic_addResturantMenu.php
class m160205_000000_seomatic_addResturantMenu (line 7) | class m160205_000000_seomatic_addResturantMenu extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 37) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160206_000000_seomatic_addGoogleAnalyticsPlugins.php
class m160206_000000_seomatic_addGoogleAnalyticsPlugins (line 7) | class m160206_000000_seomatic_addGoogleAnalyticsPlugins extends BaseMigr...
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 30) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160206_000000_seomatic_addGoogleAnalyticsSendPageView.php
class m160206_000000_seomatic_addGoogleAnalyticsSendPageView (line 7) | class m160206_000000_seomatic_addGoogleAnalyticsSendPageView extends Bas...
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 27) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160209_000000_seomatic_alterDescriptionsColumns.php
class m160209_000000_seomatic_alterDescriptionsColumns (line 7) | class m160209_000000_seomatic_alterDescriptionsColumns extends BaseMigra...
method safeUp (line 14) | public function safeUp()
FILE: migrations/m160209_000001_seomatic_addRobotsTxt.php
class m160209_000001_seomatic_addRobotsTxt (line 7) | class m160209_000001_seomatic_addRobotsTxt extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 27) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160227_000000_seomatic_addFacebookAppId.php
class m160227_000000_seomatic_addFacebookAppId (line 7) | class m160227_000000_seomatic_addFacebookAppId extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 27) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160416_000000_seomatic_addContactPoints.php
class m160416_000000_seomatic_addContactPoints (line 7) | class m160416_000000_seomatic_addContactPoints extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 34) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160509_000000_seomatic_addSiteLinksBing.php
class m160509_000000_seomatic_addSiteLinksBing (line 7) | class m160509_000000_seomatic_addSiteLinksBing extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 35) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160707_000000_seomatic_addGoogleTagManager.php
class m160707_000000_seomatic_addGoogleTagManager (line 7) | class m160707_000000_seomatic_addGoogleTagManager extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 27) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160715_000000_seomatic_addSeoImageTransforms.php
class m160715_000000_seomatic_addSeoImageTransforms (line 7) | class m160715_000000_seomatic_addSeoImageTransforms extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 66) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160723_000000_seomatic_addSeoMainEntityOfPage.php
class m160723_000000_seomatic_addSeoMainEntityOfPage (line 7) | class m160723_000000_seomatic_addSeoMainEntityOfPage extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160724_000000_seomatic_addSeoMainEntityCategory.php
class m160724_000000_seomatic_addSeoMainEntityCategory (line 7) | class m160724_000000_seomatic_addSeoMainEntityCategory extends BaseMigra...
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160811_000000_seomatic_addVimeo.php
class m160811_000000_seomatic_addVimeo (line 7) | class m160811_000000_seomatic_addVimeo extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m160904_000000_seomatic_addTwitterFacebookImages.php
class m160904_000000_seomatic_addTwitterFacebookImages (line 7) | class m160904_000000_seomatic_addTwitterFacebookImages extends BaseMigra...
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 37) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m161220_000000_seomatic_addPriceRange.php
class m161220_000000_seomatic_addPriceRange (line 7) | class m161220_000000_seomatic_addPriceRange extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m170212_000000_seomatic_addGoogleAnalyticsAnonymizeIp.php
class m170212_000000_seomatic_addGoogleAnalyticsAnonymizeIp (line 7) | class m170212_000000_seomatic_addGoogleAnalyticsAnonymizeIp extends Base...
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 27) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: migrations/m170212_000000_seomatic_addWikipedia.php
class m170212_000000_seomatic_addWikipedia (line 7) | class m170212_000000_seomatic_addWikipedia extends BaseMigration
method safeUp (line 14) | public function safeUp()
method _addColumnsAfter (line 28) | private function _addColumnsAfter($tableName, $newColumns, $afterColum...
FILE: models/Seomatic_CreatorModel.php
class Seomatic_CreatorModel (line 4) | class Seomatic_CreatorModel extends BaseModel
method defineAttributes (line 10) | protected function defineAttributes()
FILE: models/Seomatic_IdentityModel.php
class Seomatic_IdentityModel (line 4) | class Seomatic_IdentityModel extends BaseModel
method defineAttributes (line 10) | protected function defineAttributes()
FILE: models/Seomatic_MetaFieldModel.php
class Seomatic_MetaFieldModel (line 4) | class Seomatic_MetaFieldModel extends Seomatic_MetaModel
method defineAttributes (line 12) | protected function defineAttributes()
method seoTitleUnparsed (line 41) | public function seoTitleUnparsed()
method seoDescriptionUnparsed (line 51) | public function seoDescriptionUnparsed()
method seoKeywordsUnparsed (line 61) | public function seoKeywordsUnparsed()
method getJsonLD (line 71) | public function getJsonLD($element)
method isEditable (line 94) | public function isEditable()
method getCpEditUrl (line 104) | public function getCpEditUrl()
FILE: models/Seomatic_MetaModel.php
class Seomatic_MetaModel (line 4) | class Seomatic_MetaModel extends BaseElementModel
method defineAttributes (line 12) | protected function defineAttributes()
method isEditable (line 41) | public function isEditable()
method getCpEditUrl (line 51) | public function getCpEditUrl()
method seoTitle (line 62) | public function seoTitle()
method seoDescription (line 72) | public function seoDescription()
method seoKeywords (line 82) | public function seoKeywords()
method seoImage (line 92) | public function seoImage()
method seoImageId (line 109) | public function seoImageId()
FILE: models/Seomatic_SettingsModel.php
class Seomatic_SettingsModel (line 4) | class Seomatic_SettingsModel extends BaseModel
method defineAttributes (line 10) | protected function defineAttributes()
method getDefaultHumans (line 182) | public function getDefaultHumans()
method getDefaultRobots (line 203) | public function getDefaultRobots()
FILE: models/Seomatic_SiteMetaModel.php
class Seomatic_SiteMetaModel (line 4) | class Seomatic_SiteMetaModel extends BaseModel
method defineAttributes (line 10) | protected function defineAttributes()
FILE: models/Seomatic_SocialModel.php
class Seomatic_SocialModel (line 4) | class Seomatic_SocialModel extends BaseModel
method defineAttributes (line 10) | protected function defineAttributes()
FILE: records/Seomatic_MetaRecord.php
class Seomatic_MetaRecord (line 4) | class Seomatic_MetaRecord extends BaseRecord
method getTableName (line 7) | public function getTableName()
method defineAttributes (line 12) | protected function defineAttributes()
method defineRelations (line 39) | public function defineRelations()
FILE: records/Seomatic_SettingsRecord.php
class Seomatic_SettingsRecord (line 4) | class Seomatic_SettingsRecord extends BaseRecord
method getTableName (line 7) | public function getTableName()
method defineAttributes (line 12) | protected function defineAttributes()
method getDefaultHumans (line 192) | public function getDefaultHumans()
method getDefaultRobots (line 213) | public function getDefaultRobots()
method defineRelations (line 234) | public function defineRelations()
FILE: resources/js/field.js
function Plugin (line 15) | function Plugin( element, options ) {
function setPreviewFields (line 32) | function setPreviewFields() {
FILE: resources/js/identity.js
function setSelectedValue (line 7) | function setSelectedValue(whichValue) {
function fillDynamicMenu (line 11) | function fillDynamicMenu(whichValue) {
FILE: resources/js/meta.js
function setSelectedValue (line 5) | function setSelectedValue(whichValue) {
function fillDynamicMenu (line 9) | function fillDynamicMenu(whichValue) {
function updateInfoLink (line 23) | function updateInfoLink() {
FILE: services/SeomaticService.php
class SeomaticService (line 9) | class SeomaticService extends BaseApplicationComponent
method renderSiteMeta (line 31) | public function renderSiteMeta($templatePath="", $metaVars=null, $locale)
method headlessRenderSiteMeta (line 80) | public function headlessRenderSiteMeta($templatePath="", $entry = null...
method render (line 111) | public function render($templatePath="", $metaVars=null, $isPreview=fa...
method renderJSONLD (line 191) | public function renderJSONLD($object=array(), $isPreview=false)
method renderDisplayPreview (line 220) | public function renderDisplayPreview($templateName="", $metaVars)
method renderIdentity (line 245) | public function renderIdentity($metaVars, $locale, $isPreview=false)
method renderWebsite (line 256) | public function renderWebsite($metaVars, $locale, $isPreview=false)
method renderMainEntityOfPage (line 268) | public function renderMainEntityOfPage($metaVars, $locale, $isPreview=...
method renderBreadcrumbs (line 284) | public function renderBreadcrumbs($metaVars, $locale, $isPreview=false)
method renderPlace (line 302) | public function renderPlace($metaVars, $locale, $isPreview=false)
method renderGoogleTagManager (line 328) | public function renderGoogleTagManager($metaVars, $locale, $isPreview=...
method renderGoogleAnalytics (line 361) | public function renderGoogleAnalytics($metaVars, $locale, $isPreview=f...
method renderGlobals (line 393) | public function renderGlobals($metaVars, $forTemplate="")
method renderHumans (line 406) | public function renderHumans($isPreview=false)
method renderHumansTemplate (line 451) | public function renderHumansTemplate()
method renderRobots (line 477) | public function renderRobots($isPreview=false)
method renderRobotsTemplate (line 522) | public function renderRobotsTemplate()
method renderSeoMetrics (line 548) | public function renderSeoMetrics()
method getMetaFromElement (line 582) | public function getMetaFromElement($element)
method isFieldHandleInEntry (line 673) | public function isFieldHandleInEntry($entryElement = null, $fieldHandl...
method getTextFromEntryField (line 695) | public function getTextFromEntryField($srcField)
method extractTextFromTags (line 729) | public function extractTextFromTags($tags)
method extractTextFromMatrix (line 744) | public function extractTextFromMatrix($matrixBlocks, $fieldHandle="")
method extractTextFromNeo (line 772) | public function extractTextFromNeo($neoBlocks, $fieldHandle="")
method setEntryMeta (line 801) | public function setEntryMeta($entryMeta, $entryMetaUrl)
method setSocialForMeta (line 891) | public function setSocialForMeta(&$meta, $siteMeta, $social, $helper, ...
method getGlobals (line 1085) | public function getGlobals($forTemplate="", $locale)
method getDefaultBreadcrumbs (line 1227) | public function getDefaultBreadcrumbs($meta)
method getSettings (line 1279) | public function getSettings($locale)
method saveDefaultSettings (line 1376) | public function saveDefaultSettings($locale)
method getSiteMeta (line 1417) | public function getSiteMeta($locale)
method getIdentity (line 1504) | public function getIdentity($locale)
method getIdentityJSONLD (line 1653) | public function getIdentityJSONLD($identity, $helper, $locale)
method getSocial (line 1853) | public function getSocial($locale)
method getCreator (line 1892) | public function getCreator($locale)
method getCreatorJSONLD (line 1998) | public function getCreatorJSONLD($creator, $helper, $locale)
method getMainEntityOfPageJSONLD (line 2183) | public function getMainEntityOfPageJSONLD($meta, $identity, $locale, $...
method getProductJSONLD (line 2356) | public function getProductJSONLD($meta, $identity, $locale)
method getBreadcrumbsJSONLD (line 2406) | public function getBreadcrumbsJSONLD($crumbs)
method getWebSiteJSONLD (line 2438) | public function getWebSiteJSONLD($metaVars, $locale)
method parseAsTemplate (line 2503) | function parseAsTemplate($templateStr, $element)
method getMeta (line 2523) | public function getMeta($forTemplate="")
method saveMeta (line 2607) | public function saveMeta(&$model)
method getMetaById (line 2707) | public function getMetaById($metaId, $locale=null)
method addSocialHelpers (line 2718) | private function addSocialHelpers(&$helper, $social, $identity)
method addIdentityHelpers (line 2810) | private function addIdentityHelpers(&$helper, $identity)
method addCreatorHelpers (line 2868) | private function addCreatorHelpers(&$helper, $creator)
method getMetaHashStr (line 2915) | private function getMetaHashStr($templatePath, $metaVars)
method sanitizeMetaVars (line 2930) | public function sanitizeMetaVars(&$metaVars)
method getTransformsList (line 3020) | public function getTransformsList()
method getLocalizedUrls (line 3037) | public function getLocalizedUrls()
method getFullyQualifiedUrl (line 3094) | public function getFullyQualifiedUrl($url)
method extractKeywords (line 3139) | public function extractKeywords($text = null, $limit = 15, $withoutSto...
method extractSummary (line 3172) | public function extractSummary($text = null, $limit = null, $withoutSt...
method humanFileSize (line 3208) | public function humanFileSize($size)
method sanitizeArray (line 3226) | public function sanitizeArray(&$theArray)
method findOverlap (line 3260) | private function findOverlap($str1, $str2){
method replaceOverlap (line 3288) | private function replaceOverlap($str1, $str2, $length = "long"){
method _cleanupText (line 3310) | private function _cleanupText($text = null)
method _print_twig_array (line 3339) | private function _print_twig_array($theArray, $level)
method _get_hash_string (line 3441) | private function _get_hash_string($theArray)
method truncateStringOnWord (line 3462) | public function truncateStringOnWord($theString, $desiredLength)
method encodeEmailAddress (line 3493) | public function encodeEmailAddress($emailAddress)
method convertTimes (line 3510) | public function convertTimes(&$value, $timezone=null)
FILE: twigextensions/SeomaticTwigExtension.php
class SeomaticTwigExtension (line 7) | class SeomaticTwigExtension extends \Twig_Extension
method getName (line 16) | public function getName()
method getGlobals (line 25) | public function getGlobals()
method getFilters (line 50) | public function getFilters()
method getFunctions (line 68) | public function getFunctions()
method renderJSONLD (line 116) | public function renderJSONLD($object=array())
method extractKeywords (line 128) | public function extractKeywords($text = null, $limit = 15, $withoutSto...
method extractSummary (line 139) | public function extractSummary($text = null, $limit = null, $withoutSt...
method truncateStringOnWord (line 152) | public function truncateStringOnWord($theString, $desiredLength)
method encodeEmailAddress (line 163) | public function encodeEmailAddress($emailAddress)
method extractTextFromMatrix (line 174) | public function extractTextFromMatrix($matrixBlocks)
method getLocalizedUrls (line 185) | public function getLocalizedUrls()
method getFullyQualifiedUrl (line 196) | public function getFullyQualifiedUrl($url)
method _get_current_template_path (line 207) | private function _get_current_template_path()
FILE: variables/SeomaticVariable.php
class SeomaticVariable (line 4) | class SeomaticVariable
method renderJSONLD (line 45) | public function renderJSONLD($object=array())
method extractKeywords (line 57) | public function extractKeywords($text = null, $limit = 15, $withoutSto...
method extractSummary (line 68) | public function extractSummary($text = null, $limit = null, $withoutSt...
method truncateStringOnWord (line 81) | public function truncateStringOnWord($theString, $desiredLength)
method encodeEmailAddress (line 92) | public function encodeEmailAddress($emailAddress)
method extractTextFromMatrix (line 103) | public function extractTextFromMatrix($matrixBlocks)
method getLocalizedUrls (line 114) | public function getLocalizedUrls()
method getFullyQualifiedUrl (line 125) | public function getFullyQualifiedUrl($url)
method render (line 140) | function render($templatePath="", $metaVars=null)
method renderPreview (line 154) | function renderPreview($templatePath="", $forTemplate="", $elementId=n...
method renderDisplayPreview (line 198) | function renderDisplayPreview($templateName="", $forTemplate="", $elem...
method renderIdentity (line 242) | function renderIdentity($elementId=null, $locale=null, $isPreview=false)
method renderWebsite (line 268) | function renderWebsite($elementId=null, $locale=null, $isPreview=false)
method renderMainEntityOfPage (line 294) | function renderMainEntityOfPage($elementId=null, $locale=null, $isPrev...
method renderBreadcrumbs (line 320) | function renderBreadcrumbs($elementId=null, $locale=null, $isPreview=f...
method renderPlace (line 346) | function renderPlace($elementId=null, $locale=null, $isPreview=false)
method renderGoogleTagManager (line 372) | function renderGoogleTagManager($elementId=null, $locale=null, $isPrev...
method renderGoogleAnalytics (line 398) | function renderGoogleAnalytics($elementId=null, $locale=null, $isPrevi...
method renderGlobals (line 424) | function renderGlobals($forTemplate="", $elementId=null, $locale=null)
method renderHumans (line 475) | public function renderHumans($isPreview=false)
method renderHumansTemplate (line 486) | public function renderHumansTemplate()
method renderRobots (line 497) | public function renderRobots($isPreview=false)
method renderRobotsTemplate (line 508) | public function renderRobotsTemplate()
method getIdentity (line 519) | public function getIdentity($locale=null)
method getSocial (line 530) | public function getSocial($locale=null)
method getTemplateMeta (line 541) | public function getTemplateMeta($templatePath="", $locale=null)
method humanFileSize (line 552) | public function humanFileSize($size)
method getPluginName (line 561) | function getPluginName()
FILE: vendor/composer/ClassLoader.php
class ClassLoader (line 43) | class ClassLoader
method getPrefixes (line 59) | public function getPrefixes()
method getPrefixesPsr4 (line 68) | public function getPrefixesPsr4()
method getFallbackDirs (line 73) | public function getFallbackDirs()
method getFallbackDirsPsr4 (line 78) | public function getFallbackDirsPsr4()
method getClassMap (line 83) | public function getClassMap()
method addClassMap (line 91) | public function addClassMap(array $classMap)
method add (line 108) | public function add($prefix, $paths, $prepend = false)
method addPsr4 (line 155) | public function addPsr4($prefix, $paths, $prepend = false)
method set (line 200) | public function set($prefix, $paths)
method setPsr4 (line 218) | public function setPsr4($prefix, $paths)
method setUseIncludePath (line 237) | public function setUseIncludePath($useIncludePath)
method getUseIncludePath (line 248) | public function getUseIncludePath()
method setClassMapAuthoritative (line 259) | public function setClassMapAuthoritative($classMapAuthoritative)
method isClassMapAuthoritative (line 269) | public function isClassMapAuthoritative()
method register (line 279) | public function register($prepend = false)
method unregister (line 287) | public function unregister()
method loadClass (line 298) | public function loadClass($class)
method findFile (line 314) | public function findFile($class)
method findFileWithExtension (line 344) | private function findFileWithExtension($class, $ext)
function includeFile (line 410) | function includeFile($file)
FILE: vendor/composer/autoload_real.php
class ComposerAutoloaderInit5b938720cfef7b7256946290ccab109b (line 5) | class ComposerAutoloaderInit5b938720cfef7b7256946290ccab109b
method loadClassLoader (line 9) | public static function loadClassLoader($class)
method getLoader (line 16) | public static function getLoader()
FILE: vendor/composer/autoload_static.php
class ComposerStaticInit5b938720cfef7b7256946290ccab109b (line 7) | class ComposerStaticInit5b938720cfef7b7256946290ccab109b
method getInitializer (line 57) | public static function getInitializer(ClassLoader $loader)
FILE: vendor/crodas/text-rank/lib/TextRank/Config.php
class Config (line 39) | class Config
method __construct (line 44) | public function __construct()
method on (line 49) | public function on($event, Closure $callback)
method addListener (line 58) | public function addListener($object)
method trigger (line 64) | public function trigger($ev, $data)
FILE: vendor/crodas/text-rank/lib/TextRank/DefaultEvents.php
class DefaultEvents (line 39) | class DefaultEvents
method normalize_keywords (line 41) | public function normalize_keywords(Array $keywords)
method filter_keywords (line 48) | public function filter_keywords(Array $keywords)
method get_sentences (line 63) | public function get_sentences($text)
method get_words (line 69) | public function get_words($text)
FILE: vendor/crodas/text-rank/lib/TextRank/POS/English/Tagger.php
class Tagger (line 44) | class Tagger
method get (line 46) | public static function get(Array $words)
method tag (line 61) | public static function tag(Array $words)
FILE: vendor/crodas/text-rank/lib/TextRank/Stopword.php
class Stopword (line 45) | class Stopword extends DefaultEvents
method normalize_keywords (line 50) | public function normalize_keywords(Array $keywords)
method filter_keywords (line 64) | public function filter_keywords(Array $keywords)
method getClassifier (line 81) | protected function getClassifier()
method getStopwords (line 89) | protected function getStopwords()
method get_words (line 98) | public function get_words($text)
FILE: vendor/crodas/text-rank/lib/TextRank/Summary.php
class Summary (line 39) | class Summary extends TextRank
method getSummary (line 41) | public function getSummary($text)
FILE: vendor/crodas/text-rank/lib/TextRank/SummaryPageRank.php
class SummaryPageRank (line 41) | class SummaryPageRank extends Pagerank
method getGraph (line 43) | protected function getGraph(Array $sentences)
FILE: vendor/crodas/text-rank/lib/TextRank/TextRank.php
class TextRank (line 41) | class TextRank
method __construct (line 45) | public function __construct(Config $config)
method getAllKeywordsSorted (line 50) | public function getAllKeywordsSorted($text)
method getKeywords (line 125) | public function getKeywords($text, $limit = 20)
FILE: vendor/crodas/text-rank/tests/QuickTest.php
class QuickTest (line 3) | class QuickTest extends \phpunit_framework_testcase
method provider (line 5) | public static function provider()
method testGetkeywordsSimpler (line 16) | public function testGetkeywordsSimpler($text, $expected)
method testSentences (line 36) | public function testSentences($text, $expected, $esummary)
method testGetkeywords (line 49) | public function testGetkeywords($text, $expected)
FILE: vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Maths.php
class Maths (line 5) | class Maths
method normaliseScore (line 23) | public static function normaliseScore($score, $min, $max, $dps = 1)
method bcCalc (line 63) | public static function bcCalc($number1, $action, $number2, $round = fa...
method normaliseOperator (line 92) | public static function normaliseOperator($operator)
method performCalc (line 133) | private static function performCalc($number1, $action, $number2, $roun...
FILE: vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Pluralise.php
class Pluralise (line 5) | class Pluralise
method getPlural (line 114) | public static function getPlural($string)
method getSingular (line 153) | public static function getSingular($string)
FILE: vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Resource.php
class Resource (line 5) | class Resource
method fetchSpacheWordList (line 24) | public static function fetchSpacheWordList()
method fetchDaleChallWordList (line 42) | public static function fetchDaleChallWordList()
FILE: vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Syllables.php
class Syllables (line 5) | class Syllables
method syllableCount (line 251) | public static function syllableCount($strWord, $strEncoding = '')
method totalSyllables (line 337) | public static function totalSyllables($strText, $strEncoding = '')
method averageSyllablesPerWord (line 355) | public static function averageSyllablesPerWord($strText, $strEncoding ...
method wordsWithThreeSyllables (line 374) | public static function wordsWithThreeSyllables($strText, $blnCountProp...
method percentageWordsWithThreeSyllables (line 402) | public static function percentageWordsWithThreeSyllables($strText, $bl...
FILE: vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Text.php
class Text (line 5) | class Text
method cleanText (line 24) | public static function cleanText($strText)
method lowerCase (line 129) | public static function lowerCase($strText, $strEncoding = '')
method upperCase (line 155) | public static function upperCase($strText, $strEncoding = '')
method substring (line 183) | public static function substring($strText, $intStart, $intLength, $str...
method textLength (line 209) | public static function textLength($strText, $strEncoding = '')
method characterCount (line 235) | public static function characterCount($strText, $strEncoding = '')
method letterCount (line 247) | public static function letterCount($strText, $strEncoding = '')
method wordCount (line 284) | public static function wordCount($strText, $strEncoding = '')
method sentenceCount (line 302) | public static function sentenceCount($strText, $strEncoding = '')
method averageWordsPerSentence (line 320) | public static function averageWordsPerSentence($strText, $strEncoding ...
FILE: vendor/davechild/textstatistics/src/DaveChild/TextStatistics/TextStatistics.php
class TextStatistics (line 39) | class TextStatistics
method __construct (line 69) | public function __construct($strEncoding = '')
method setText (line 82) | public function setText($strText)
method setEncoding (line 98) | public function setEncoding($strEncoding)
method fleschKincaidReadingEase (line 109) | public function fleschKincaidReadingEase($strText = false)
method fleschKincaidGradeLevel (line 143) | public function fleschKincaidGradeLevel($strText = false)
method gunningFogScore (line 177) | public function gunningFogScore($strText = false)
method colemanLiauIndex (line 203) | public function colemanLiauIndex($strText = false)
method smogIndex (line 245) | public function smogIndex($strText = false)
method automatedReadabilityIndex (line 283) | public function automatedReadabilityIndex($strText = false)
method daleChallReadabilityScore (line 325) | public function daleChallReadabilityScore($strText = false)
method spacheReadabilityScore (line 367) | public function spacheReadabilityScore($strText = false)
method daleChallDifficultWordCount (line 405) | public function daleChallDifficultWordCount($strText = false)
method spacheDifficultWordCount (line 432) | public function spacheDifficultWordCount($strText = false)
method letterCount (line 465) | public function letterCount($strText = false)
method sentenceCount (line 477) | public function sentenceCount($strText = false)
method wordCount (line 489) | public function wordCount($strText = false)
method averageWordsPerSentence (line 501) | public function averageWordsPerSentence($strText = false)
method syllableCount (line 513) | public function syllableCount($strText = false)
method totalSyllables (line 525) | public function totalSyllables($strText = false)
method averageSyllablesPerWord (line 537) | public function averageSyllablesPerWord($strText = false)
method wordsWithThreeSyllables (line 550) | public function wordsWithThreeSyllables($strText = false, $blnCountPro...
method percentageWordsWithThreeSyllables (line 563) | public function percentageWordsWithThreeSyllables($strText = false, $b...
method flesch_kincaid_reading_ease (line 574) | public function flesch_kincaid_reading_ease($strText = false)
method flesch_kincaid_grade_level (line 579) | public function flesch_kincaid_grade_level($strText = false)
method gunning_fog_score (line 584) | public function gunning_fog_score($strText = false)
method coleman_liau_index (line 589) | public function coleman_liau_index($strText = false)
method smog_index (line 594) | public function smog_index($strText = false)
method automated_readability_index (line 599) | public function automated_readability_index($strText = false)
method dale_chall_readability_score (line 604) | public function dale_chall_readability_score($strText = false)
method spache_readability_score (line 609) | public function spache_readability_score($strText = false)
FILE: vendor/davechild/textstatistics/tests/TextStatisticsCMULexTest.php
class TextStatisticsTestCMULex (line 3) | class TextStatisticsTestCMULex extends PHPUnit_Framework_TestCase
method setUp (line 14) | public function setUp()
method tearDown (line 20) | public function tearDown()
method testSyllableCountFailingCMUWords (line 28) | public function testSyllableCountFailingCMUWords()
FILE: vendor/davechild/textstatistics/tests/TextStatisticsKiplingIfTest.php
class TextStatisticsKiplingIf (line 3) | class TextStatisticsKiplingIf extends PHPUnit_Framework_TestCase
method setUp (line 83) | public function setUp()
method tearDown (line 89) | public function tearDown()
method testKiplingSyllables (line 96) | public function testKiplingSyllables()
method testLetterCount (line 394) | public function testLetterCount()
method testSyllableCount (line 401) | public function testSyllableCount()
method testWordCount (line 408) | public function testWordCount()
method testSentenceCount (line 415) | public function testSentenceCount()
method testTextLengthCheck (line 422) | public function testTextLengthCheck()
method testFleschKincaidReadingEase (line 429) | public function testFleschKincaidReadingEase()
method testFleschKincaidGradeLevel (line 436) | public function testFleschKincaidGradeLevel()
method testGunningFogScore (line 443) | public function testGunningFogScore()
method testColemanLiauIndex (line 450) | public function testColemanLiauIndex()
method testSMOGIndex (line 457) | public function testSMOGIndex()
method testAutomatedReadabilityIndex (line 464) | public function testAutomatedReadabilityIndex()
FILE: vendor/davechild/textstatistics/tests/TextStatisticsMaths.php
class TextStatisticsMaths (line 3) | class TextStatisticsMaths extends PHPUnit_Framework_TestCase
method setUp (line 16) | public function setUp()
method tearDown (line 22) | public function tearDown()
method testNormalisation (line 29) | public function testNormalisation()
method testCalc (line 44) | public function testCalc()
FILE: vendor/davechild/textstatistics/tests/TextStatisticsMelvilleMobyDickTest.php
class TextStatisticsMelvilleMobyDick (line 3) | class TextStatisticsMelvilleMobyDick extends PHPUnit_Framework_TestCase
method setUp (line 49) | public function setUp()
method tearDown (line 55) | public function tearDown()
method testMobyDickSyllables (line 62) | public function testMobyDickSyllables()
method testWordCount (line 269) | public function testWordCount()
method testLongWordCount (line 276) | public function testLongWordCount()
method testSentenceCount (line 284) | public function testSentenceCount()
method testTextLengthCheck (line 291) | public function testTextLengthCheck()
method testFleschKincaidReadingEase (line 298) | public function testFleschKincaidReadingEase()
method testFleschKincaidGradeLevel (line 305) | public function testFleschKincaidGradeLevel()
method testGunningFogScore (line 312) | public function testGunningFogScore()
method testColemanLiauIndex (line 319) | public function testColemanLiauIndex()
method testSMOGIndex (line 326) | public function testSMOGIndex()
method testAutomatedReadabilityIndex (line 333) | public function testAutomatedReadabilityIndex()
FILE: vendor/davechild/textstatistics/tests/TextStatisticsPluralise.php
class TextStatisticsPluralise (line 3) | class TextStatisticsPluralise extends PHPUnit_Framework_TestCase
method setUp (line 16) | public function setUp()
method tearDown (line 22) | public function tearDown()
method testPluralisation (line 29) | public function testPluralisation()
method testSingularisation (line 47) | public function testSingularisation()
FILE: vendor/davechild/textstatistics/tests/TextStatisticsTest.php
class TextStatisticsTest (line 3) | class TextStatisticsTest extends PHPUnit_Framework_TestCase
method setUp (line 16) | public function setUp()
method tearDown (line 22) | public function tearDown()
method testCleaning (line 29) | public function testCleaning()
method testCases (line 37) | public function testCases()
method testCounts (line 51) | public function testCounts()
method testSyllableCountBasicWords (line 71) | public function testSyllableCountBasicWords()
method testSyllableCountComplexWords (line 95) | public function testSyllableCountComplexWords()
method testSyllableCountProgrammedExceptions (line 181) | public function testSyllableCountProgrammedExceptions()
method testAverageSyllablesPerWord (line 190) | public function testAverageSyllablesPerWord()
method testWordCount (line 199) | public function testWordCount()
method testCheckPercentageWordsWithThreeSyllables (line 214) | public function testCheckPercentageWordsWithThreeSyllables()
method testSentenceCount (line 228) | public function testSentenceCount()
method testAverageWordsPerSentence (line 244) | public function testAverageWordsPerSentence()
method testFleschKincaidReadingEase (line 260) | public function testFleschKincaidReadingEase()
method testFleschKincaidGradeLevel (line 270) | public function testFleschKincaidGradeLevel()
method testGunningFogScore (line 280) | public function testGunningFogScore()
method testColemanLiauIndex (line 291) | public function testColemanLiauIndex()
method testSMOGIndex (line 301) | public function testSMOGIndex()
method testAutomatedReadabilityIndex (line 311) | public function testAutomatedReadabilityIndex()
FILE: vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php
class HtmlDomParser (line 7) | class HtmlDomParser {
method file_get_html (line 12) | static public function file_get_html() {
method str_get_html (line 20) | static public function str_get_html() {
FILE: vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/simple_html_dom.php
function file_get_html (line 76) | function file_get_html($url, $use_include_path = false, $context=null, $...
function str_get_html (line 94) | function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $tar...
function dump_html_tree (line 107) | function dump_html_tree($node, $show_attr=true, $deep=0)
class simple_html_dom_node (line 120) | class simple_html_dom_node
method __construct (line 134) | function __construct($dom)
method __destruct (line 140) | function __destruct()
method __toString (line 145) | function __toString()
method clear (line 151) | function clear()
method dump (line 160) | function dump($show_attr=true, $deep=0)
method dump_node (line 185) | function dump_node($echo=true)
method parent (line 251) | function parent($parent=null)
method has_child (line 266) | function has_child()
method children (line 272) | function children($idx=-1)
method first_child (line 283) | function first_child()
method last_child (line 293) | function last_child()
method next_sibling (line 303) | function next_sibling()
method prev_sibling (line 324) | function prev_sibling()
method find_ancestor_tag (line 336) | function find_ancestor_tag($tag)
method innertext (line 358) | function innertext()
method outertext (line 370) | function outertext()
method text (line 430) | function text()
method xmltext (line 471) | function xmltext()
method makeup (line 480) | function makeup()
method find (line 516) | function find($selector, $idx=null, $lowercase=false)
method seek (line 567) | protected function seek($selector, &$ret, $lowercase=false)
method match (line 664) | protected function match($exp, $pattern, $value) {
method parse_selector (line 686) | protected function parse_selector($selector_string) {
method __get (line 734) | function __get($name) {
method __set (line 748) | function __set($name, $value) {
method __isset (line 762) | function __isset($name) {
method __unset (line 772) | function __unset($name) {
method convert_text (line 778) | function convert_text($text)
method is_utf8 (line 830) | static function is_utf8($str)
method get_display_size (line 875) | function get_display_size()
method getAllAttributes (line 956) | function getAllAttributes() {return $this->attr;}
method getAttribute (line 957) | function getAttribute($name) {return $this->__get($name);}
method setAttribute (line 958) | function setAttribute($name, $value) {$this->__set($name, $value);}
method hasAttribute (line 959) | function hasAttribute($name) {return $this->__isset($name);}
method removeAttribute (line 960) | function removeAttribute($name) {$this->__set($name, null);}
method getElementById (line 961) | function getElementById($id) {return $this->find("#$id", 0);}
method getElementsById (line 962) | function getElementsById($id, $idx=null) {return $this->find("#$id", $...
method getElementByTagName (line 963) | function getElementByTagName($name) {return $this->find($name, 0);}
method getElementsByTagName (line 964) | function getElementsByTagName($name, $idx=null) {return $this->find($n...
method parentNode (line 965) | function parentNode() {return $this->parent();}
method childNodes (line 966) | function childNodes($idx=-1) {return $this->children($idx);}
method firstChild (line 967) | function firstChild() {return $this->first_child();}
method lastChild (line 968) | function lastChild() {return $this->last_child();}
method nextSibling (line 969) | function nextSibling() {return $this->next_sibling();}
method previousSibling (line 970) | function previousSibling() {return $this->prev_sibling();}
method hasChildNodes (line 971) | function hasChildNodes() {return $this->has_child();}
method nodeName (line 972) | function nodeName() {return $this->tag;}
method appendChild (line 973) | function appendChild($node) {$node->parent($this); return $node;}
class simple_html_dom (line 985) | class simple_html_dom
method __construct (line 1029) | function __construct($str=null, $lowercase=true, $forceTagsClosed=true...
method __destruct (line 1049) | function __destruct()
method load (line 1055) | function load($str, $lowercase=true, $stripRN=true, $defaultBRText=DEF...
method load_file (line 1092) | function load_file()
method set_callback (line 1104) | function set_callback($function_name)
method remove_callback (line 1110) | function remove_callback()
method save (line 1116) | function save($filepath='')
method find (line 1125) | function find($selector, $idx=null, $lowercase=false)
method clear (line 1131) | function clear()
method dump (line 1142) | function dump($show_attr=true)
method prepare (line 1148) | protected function prepare($str, $lowercase=true, $stripRN=true, $defa...
method parse (line 1183) | protected function parse()
method parse_charset (line 1201) | protected function parse_charset()
method read_tag (line 1272) | protected function read_tag()
method parse_attr (line 1497) | protected function parse_attr($node, $name, &$space)
method link_nodes (line 1534) | protected function link_nodes(&$node, $is_child)
method as_text_node (line 1545) | protected function as_text_node($tag)
method skip (line 1555) | protected function skip($chars)
method copy_skip (line 1561) | protected function copy_skip($chars)
method copy_until (line 1571) | protected function copy_until($chars)
method copy_until_char (line 1580) | protected function copy_until_char($char)
method copy_until_char_escape (line 1598) | protected function copy_until_char_escape($char)
method remove_noise (line 1629) | protected function remove_noise($pattern, $remove_tag=false)
method restore_noise (line 1654) | function restore_noise($text)
method search_noise (line 1687) | function search_noise($text)
method __toString (line 1700) | function __toString()
method __get (line 1705) | function __get($name)
method childNodes (line 1723) | function childNodes($idx=-1) {return $this->root->childNodes($idx);}
method firstChild (line 1724) | function firstChild() {return $this->root->first_child();}
method lastChild (line 1725) | function lastChild() {return $this->root->last_child();}
method createElement (line 1726) | function createElement($name, $value=null) {return @str_get_html("<$na...
method createTextNode (line 1727) | function createTextNode($value) {return @end(str_get_html($value)->nod...
method getElementById (line 1728) | function getElementById($id) {return $this->find("#$id", 0);}
method getElementsById (line 1729) | function getElementsById($id, $idx=null) {return $this->find("#$id", $...
method getElementByTagName (line 1730) | function getElementByTagName($name) {return $this->find($name, 0);}
method getElementsByTagName (line 1731) | function getElementsByTagName($name, $idx=-1) {return $this->find($nam...
method loadFile (line 1732) | function loadFile() {$args = func_get_args();$this->load_file($args);}
Condensed preview — 182 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8,984K chars).
[
{
"path": ".gitignore",
"chars": 33,
"preview": "bower_components\n.DS_Store\n.idea\n"
},
{
"path": "CHANGELOG.md",
"chars": 33000,
"preview": "# SEOmatic Changelog\n\n## 1.1.56 - 2017.11.10\n### Changed\n* Fixed a regression that would cause field sources to not appe"
},
{
"path": "DOCS.md",
"chars": 122429,
"preview": "# SEOmatic plugin for Craft\n\nA turnkey SEO implementation for Craft CMS that is comprehensive, powerful, and flexible.\n\n"
},
{
"path": "LICENSE.txt",
"chars": 1157,
"preview": "The SEOmatic License\nCopyright (c) 2015 nystudio107\n\nPermission is hereby granted, free of charge, to any person or enti"
},
{
"path": "README.md",
"chars": 4688,
"preview": "[](http://unmaintained.tech/)\n\n# DEPRECATED\n\nThis Craft CM"
},
{
"path": "SeomaticPlugin.php",
"chars": 5652,
"preview": "<?php\nnamespace Craft;\n\nclass SeomaticPlugin extends BasePlugin\n{\n public function getName()\n {\n $pluginNam"
},
{
"path": "composer.json",
"chars": 409,
"preview": "{\n \"name\": \"nystudio107/seomatic\",\n\t\"minimum-stability\": \"dev\",\n \"description\": \"A turnkey SEO implementation for "
},
{
"path": "config.php",
"chars": 4844,
"preview": "<?php\n/**\n * SEOmatic Configuration\n *\n * Completely optional configuration settings for SEOmatic if you want to customi"
},
{
"path": "controllers/SeomaticController.php",
"chars": 63173,
"preview": "<?php\nnamespace Craft;\n\nuse \\DaveChild\\TextStatistics as TS;\nuse \\Sunra\\PhpSimple\\HtmlDomParser;\n\nclass SeomaticControll"
},
{
"path": "elementtypes/Seomatic_MetaElementType.php",
"chars": 4807,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_MetaElementType extends BaseElementType\n{\n\n public function getName()\n {\n "
},
{
"path": "fieldtypes/Seomatic_MetaFieldType.php",
"chars": 23884,
"preview": "<?php\nnamespace Craft;\n\n/**\n * Seomatic Meta field type\n */\nclass Seomatic_MetaFieldType extends BaseFieldType\n{\n\n pu"
},
{
"path": "migrations/m151225_000000_seomatic_addHumansField.php",
"chars": 1508,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m151226_000000_seomatic_addTwitterFacebookFields.php",
"chars": 1794,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160101_000000_seomatic_addRobotsFields.php",
"chars": 1679,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160111_000000_seomatic_addTitleFields.php",
"chars": 1856,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160122_000000_seomatic_addTypeFields.php",
"chars": 2151,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160123_000000_seomatic_addOpeningHours.php",
"chars": 2358,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160202_000000_seomatic_addSocialHandles.php",
"chars": 2030,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160204_000000_seomatic_addGoogleAnalytics.php",
"chars": 1870,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160205_000000_seomatic_addResturantMenu.php",
"chars": 2218,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160206_000000_seomatic_addGoogleAnalyticsPlugins.php",
"chars": 2008,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160206_000000_seomatic_addGoogleAnalyticsSendPageView.php",
"chars": 1821,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160209_000000_seomatic_alterDescriptionsColumns.php",
"chars": 714,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160209_000001_seomatic_addRobotsTxt.php",
"chars": 1483,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160227_000000_seomatic_addFacebookAppId.php",
"chars": 1498,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160416_000000_seomatic_addContactPoints.php",
"chars": 2094,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160509_000000_seomatic_addSiteLinksBing.php",
"chars": 2103,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160707_000000_seomatic_addGoogleTagManager.php",
"chars": 1804,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160715_000000_seomatic_addSeoImageTransforms.php",
"chars": 4661,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160723_000000_seomatic_addSeoMainEntityOfPage.php",
"chars": 1498,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160724_000000_seomatic_addSeoMainEntityCategory.php",
"chars": 1502,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160811_000000_seomatic_addVimeo.php",
"chars": 1594,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m160904_000000_seomatic_addTwitterFacebookImages.php",
"chars": 1809,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m161220_000000_seomatic_addPriceRange.php",
"chars": 1641,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m170212_000000_seomatic_addGoogleAnalyticsAnonymizeIp.php",
"chars": 1822,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "migrations/m170212_000000_seomatic_addWikipedia.php",
"chars": 1600,
"preview": "<?php\r\nnamespace Craft;\r\n\r\n/**\r\n * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migr"
},
{
"path": "models/Seomatic_CreatorModel.php",
"chars": 2886,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_CreatorModel extends BaseModel\n{\n /**\n * @access protected\n * @return "
},
{
"path": "models/Seomatic_IdentityModel.php",
"chars": 3073,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_IdentityModel extends BaseModel\n{\n /**\n * @access protected\n * @return"
},
{
"path": "models/Seomatic_MetaFieldModel.php",
"chars": 3688,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_MetaFieldModel extends Seomatic_MetaModel\n{\n protected $elementType = 'Seomati"
},
{
"path": "models/Seomatic_MetaModel.php",
"chars": 3550,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_MetaModel extends BaseElementModel\n{\n protected $elementType = 'Seomatic_Meta'"
},
{
"path": "models/Seomatic_SettingsModel.php",
"chars": 14460,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_SettingsModel extends BaseModel\n{\n /**\n * @access protected\n * @return"
},
{
"path": "models/Seomatic_SiteMetaModel.php",
"chars": 1128,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_SiteMetaModel extends BaseModel\n{\n /**\n * @access protected\n * @return"
},
{
"path": "models/Seomatic_SocialModel.php",
"chars": 1084,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_SocialModel extends BaseModel\n{\n /**\n * @access protected\n * @return a"
},
{
"path": "records/Seomatic_MetaRecord.php",
"chars": 2553,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_MetaRecord extends BaseRecord\n{\n\n public function getTableName()\n {\n "
},
{
"path": "records/Seomatic_SettingsRecord.php",
"chars": 15252,
"preview": "<?php\nnamespace Craft;\n\nclass Seomatic_SettingsRecord extends BaseRecord\n{\n\n public function getTableName()\n {\n "
},
{
"path": "releases.json",
"chars": 49877,
"preview": "[\n {\n \"version\": \"1.1.56\",\n \"downloadUrl\": \"https://github.com/nystudio107/seomatic/archive/master.zip\""
},
{
"path": "resources/css/bootstrap-tokenfield.css",
"chars": 4773,
"preview": "/*!\n * bootstrap-tokenfield\n * https://github.com/sliptree/bootstrap-tokenfield\n * Copyright 2013-2014 Sliptree and othe"
},
{
"path": "resources/css/css-reset.css",
"chars": 183,
"preview": ".token {\n display: inline;\n border: none;\n border-radius: 0;\n padding: 0;\n font-size: inherit;\n line-h"
},
{
"path": "resources/css/field.css",
"chars": 2958,
"preview": "div.seomatic-livepreviewbtn {\n background-color: #fafafa!important;\n\tbackground-image: -webkit-linear-gradient(white,"
},
{
"path": "resources/css/seo-metrics-style.css",
"chars": 518,
"preview": "body.seo-metrics {\n background-color: #FFF;\n}\n\ndiv.score-display {\n padding-top: 10px;\n padding-left: 30px;\n}\n\n"
},
{
"path": "resources/css/style.css",
"chars": 16152,
"preview": "div.seomatic-devmode-wrapper {\n\twidth: 100%;\n\tmargin-bottom: 10px;\n\tbackground-color: #333f4d;\n}\n\ndiv.seomatic-devmode {"
},
{
"path": "resources/js/creator.js",
"chars": 1758,
"preview": "// LOAD EVENTS\n\n$(function () {\n\n $('.metaPane').hide();\n var value = $('#siteCreatorType').val();\n value = val"
},
{
"path": "resources/js/field.js",
"chars": 7234,
"preview": "/*\n * Functionality for Seomatic MetaField fieldtype\n * by Andrew Welch - http://nystudio107.com\n *\n * Depends on: jQuer"
},
{
"path": "resources/js/field_settings.js",
"chars": 1900,
"preview": "/*\n * Functionality for Seomatic MetaField fieldtype settings\n * by Andrew Welch - http://nystudio107.com\n *\n * Depends "
},
{
"path": "resources/js/identity.js",
"chars": 4745,
"preview": "// LOAD EVENTS\n\n/* -- Define our dynamic XXX drop-down menu items */\n\nvar selectedItem = \"\";\n\nfunction setSelectedValue("
},
{
"path": "resources/js/main_entity_type_list.js",
"chars": 22073,
"preview": "var main_enitity_items = {\n 'CreativeWork': [\n {value: '', name: ''},\n {value: \"Article\", name: \"Articl"
},
{
"path": "resources/js/meta.js",
"chars": 2071,
"preview": "var selectedItem = \"\";\nif (typeof metaFieldPrefix == 'undefined')\n var metaFieldPrefix = \"\";\n\nfunction setSelectedVal"
},
{
"path": "resources/js/metalist.js",
"chars": 209,
"preview": "// LOAD EVENTS\n\n$(function () {\n\n // Behavior for \"New Meta\" button\n $('#new-meta').on('click', function () {\n "
},
{
"path": "resources/js/seomatic.js",
"chars": 783,
"preview": "// LOAD EVENTS\n\n$(function () {\n\n $('#preview-seometrics').on('click', function(e) {\n\n // Prevents the default"
},
{
"path": "resources/js/site.js",
"chars": 369,
"preview": "// LOAD EVENTS\n\n$(function () {\n\n $('#siteSeoKeywords').tokenfield({\n createTokensOnBlur: true,\n });\n\n "
},
{
"path": "resources/js/type_list.js",
"chars": 10685,
"preview": "var items = {\n 'Airline': [\n {value: '', name: ''},\n ],\n 'Corporation': [\n {value: '', name:"
},
{
"path": "services/SeomaticService.php",
"chars": 145187,
"preview": "<?php\nnamespace Craft;\n\nuse \\crodas\\TextRank\\Config;\nuse \\crodas\\TextRank\\TextRank;\nuse \\crodas\\TextRank\\Summary;\nuse \\c"
},
{
"path": "templates/_error.twig",
"chars": 277,
"preview": "{% includeCssResource \"css/craft.css\" %}\n\n{% includeJsResource \"seomatic/js/jquery-2.2.4.min.js\" %}\n{% includeCssResourc"
},
{
"path": "templates/_facebookDisplayPreview.twig",
"chars": 1617,
"preview": "{% if seomaticMeta.og is defined and seomaticMeta.og %}\n<div class=\"Facebook-container\">\n <div class=\"\">\n <a h"
},
{
"path": "templates/_googleAnalytics.twig",
"chars": 1195,
"preview": "{% if seomaticHelper.ownerGoogleAnalyticsUID %}\n<script>\n (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i["
},
{
"path": "templates/_googleDisplayPreview.twig",
"chars": 607,
"preview": "<div class=\"rc\" data-hveid=\"27\">\n\t<h3 class=\"googleDisplay\">\n\t\t<a class=\"googleDisplay\" href=\"{{ seomaticMeta.canonicalU"
},
{
"path": "templates/_googleTagManager.twig",
"chars": 606,
"preview": "{% if seomaticHelper.ownerGoogleTagManagerID %}\n<script>\n {{ gtmDataLayerVariableName }} = [{% if dataLayer is defined "
},
{
"path": "templates/_humans.twig",
"chars": 88,
"preview": "{% header \"Content-Type: text/plain\" %}\n{{ craft.seomatic.renderHumansTemplate() |raw }}"
},
{
"path": "templates/_humansDefault.twig",
"chars": 518,
"preview": "/* TEAM */\n\n{% if seomaticCreator.name is defined and seomaticCreator.name %}\nCreator: {{ seomaticCreator.name }}\n{% end"
},
{
"path": "templates/_humansPreview.twig",
"chars": 49,
"preview": "{{ craft.seomatic.renderHumansTemplate() | raw }}"
},
{
"path": "templates/_preview_display_modal.twig",
"chars": 2077,
"preview": "\t<div id=\"preview-display-popup\" style=\"display: none;\">\n\t\t<div class=\"preview-modal\">\n\t\t\t<div class=\"preview-modal-inne"
},
{
"path": "templates/_preview_humans_modal.twig",
"chars": 1340,
"preview": "\t<div id=\"preview-humans-popup\" style=\"display: none;\">\n\t\t<div class=\"preview-modal\">\n\t\t\t<div class=\"preview-modal-inner"
},
{
"path": "templates/_preview_robots_modal.twig",
"chars": 1434,
"preview": " <div id=\"preview-robots-popup\" style=\"display: none;\">\n <div class=\"preview-modal\">\n <div class=\"p"
},
{
"path": "templates/_preview_tags_modal.twig",
"chars": 8114,
"preview": " <div id=\"preview-tags-popup\" style=\"display: none;\">\n <div class=\"preview-modal\">\n <div class=\"pre"
},
{
"path": "templates/_robots.twig",
"chars": 88,
"preview": "{% header \"Content-Type: text/plain\" %}\n{{ craft.seomatic.renderRobotsTemplate() |raw }}"
},
{
"path": "templates/_robotsDefault.twig",
"chars": 375,
"preview": "# robots.txt for {{ siteUrl }}\n# For a multi-environment setup, see: https://nystudio107.com/blog/prevent-google-from-in"
},
{
"path": "templates/_robotsPreview.twig",
"chars": 49,
"preview": "{{ craft.seomatic.renderRobotsTemplate() | raw }}"
},
{
"path": "templates/_seo_meta.twig",
"chars": 6553,
"preview": "<!-- BEGIN SEOmatic rendered SEO Meta -->\n\n<title>{% if craft.config.devMode %}{{ seomaticSiteMeta.siteDevModeTitle }} {"
},
{
"path": "templates/_seo_metaPreview.twig",
"chars": 9290,
"preview": "<!-- BEGIN SEOmatic rendered SEO Meta -->\n\n<title>{% if craft.config.devMode %}{{ seomaticSiteMeta.siteDevModeTitle }} {"
},
{
"path": "templates/_seo_metrics.twig",
"chars": 34712,
"preview": "<html>\n <head>\n {% includeCssResource \"css/craft.css\" %}\n\n {% includeJsResource \"seomatic/js/jquery-2.2.4.min.j"
},
{
"path": "templates/_seo_metrics_floater.twig",
"chars": 5260,
"preview": "<style>\ndiv.seomatic-metrics-floater {\n position: fixed;\n left: 10px;\n bottom: 10px;\n padding: 8px;\n bord"
},
{
"path": "templates/_seomatic_tabs.twig",
"chars": 231,
"preview": "{%- set tabs = {\n\tmeta:\t\t{ label: \"SEO Template Meta\"|t, url: url('seomatic/meta') },\n\tidentity:\t{ label: \"Site Identity"
},
{
"path": "templates/_twitterCardDisplayPreview.twig",
"chars": 1904,
"preview": "{% if seomaticMeta.twitter is defined and seomaticMeta.twitter %}\n{% set lg = false %}\n{% if seomaticMeta.twitter.card ="
},
{
"path": "templates/creator/_edit.twig",
"chars": 29871,
"preview": "{% extends \"_layouts/cp\" %}\n{% import '_includes/forms' as forms %}\n\n{% includeCssResource \"css/entry.css\" %}\n{% include"
},
{
"path": "templates/field.twig",
"chars": 27213,
"preview": "{% import \"_includes/forms\" as forms %}\n\n{% set locale = craft.isLocalized() ? (element ? element.locale : craft.locale)"
},
{
"path": "templates/field_settings.twig",
"chars": 19375,
"preview": "{% import \"_includes/forms\" as forms %}\n\n<div>\n {% if assetSources %}\n {{ forms.checkboxSelectField({\n "
},
{
"path": "templates/identity/_edit.twig",
"chars": 46097,
"preview": "{% extends \"_layouts/cp\" %}\n{% import '_includes/forms' as forms %}\n\n{% includeCssResource \"css/entry.css\" %}\n{% include"
},
{
"path": "templates/index.twig",
"chars": 41,
"preview": "{% redirect url('seomatic/seometrics') %}"
},
{
"path": "templates/json-ld/_json-ld.twig",
"chars": 848,
"preview": "{# --------------------------------------------------------------------------------\nThis is rendered via \n--------------"
},
{
"path": "templates/json-ld/_json-ld_core.twig",
"chars": 943,
"preview": "{% for key,value in object %}\n{% if value is iterable %}{% if value|keys|first==\"0\" %}{%for i in 0..level %} {% endfo"
},
{
"path": "templates/meta/_edit.twig",
"chars": 7753,
"preview": "{% extends '_layouts/cp' %}\n{% import '_includes/forms' as forms %}\n\n{% includeCssResource \"css/entry.css\" %}\n{% include"
},
{
"path": "templates/meta/_main.twig",
"chars": 12997,
"preview": "\n{{ forms.textField({\n\tlabel: \"Title\"|t,\n\tid: 'title',\n\tclass: 'nicetext',\n\tname: 'title',\n\tvalue: meta.title,\n\terrors: "
},
{
"path": "templates/meta/_sidebar.twig",
"chars": 144,
"preview": "{{ forms.lightswitchField({\n\tlabel: \"Enabled\"|t,\n\tinstructions: 'Set to \"0\" for unlimited views.'|t,\n\tname: 'enabled',\n\t"
},
{
"path": "templates/meta/index.twig",
"chars": 1390,
"preview": "{% extends '_layouts/elementindex' %}\n\n{% includeCssResource \"seomatic/css/style.css\" %}\n{% includeJsResource \"seomatic/"
},
{
"path": "templates/seometrics.twig",
"chars": 7176,
"preview": "{% import \"_includes/forms\" as forms %}\n\n{% extends \"_layouts/cp\" %}\n{% import '_includes/forms' as forms %}\n\n{% set tit"
},
{
"path": "templates/settings.twig",
"chars": 2471,
"preview": "{% import \"_includes/forms\" as forms %}\n\n{% extends \"_layouts/cp\" %}\n{% import '_includes/forms' as forms %}\n\n{% set tit"
},
{
"path": "templates/site/_edit.twig",
"chars": 28017,
"preview": "{% extends \"_layouts/cp\" %}\n{% import '_includes/forms' as forms %}\n\n{% includeCssResource \"css/entry.css\" %}\n{% include"
},
{
"path": "templates/social/_edit.twig",
"chars": 12772,
"preview": "{% extends \"_layouts/cp\" %}\n{% import '_includes/forms' as forms %}\n\n{% includeCssResource \"css/entry.css\" %}\n{% include"
},
{
"path": "templates/welcome.twig",
"chars": 2145,
"preview": "{% extends '_layouts/cp' %}\n{% set title = 'Welcome to SEOmatic!' %}\n\n{% includeCssResource \"seomatic/css/style.css\" %}\n"
},
{
"path": "translations/fr.php",
"chars": 62126,
"preview": "<?php\n\nreturn array (\n\t'SEOmatic' => 'SEOmatic',\n\t'Untitled Meta' => 'Meta sans nom',\n\t'SEO Template Meta' => 'Meta du g"
},
{
"path": "translations/nl.php",
"chars": 1329,
"preview": "<?php\n\nreturn array(\n\t'Site Creator' => 'Site Ontwikkelaar',\n\t'Site Identity' => 'Site Identiteit',\n\t'Google Site Verifi"
},
{
"path": "twigextensions/SeomaticTwigExtension.php",
"chars": 9570,
"preview": "<?php\nnamespace Craft;\n\nuse Twig_Extension;\nuse Twig_Filter_Method;\n\nclass SeomaticTwigExtension extends \\Twig_Extension"
},
{
"path": "variables/SeomaticVariable.php",
"chars": 20715,
"preview": "<?php\nnamespace Craft;\n\nclass SeomaticVariable\n{\n\n/* ==================================================================="
},
{
"path": "vendor/autoload.php",
"chars": 183,
"preview": "<?php\n\n// autoload.php @generated by Composer\n\nrequire_once __DIR__ . '/composer' . '/autoload_real.php';\n\nreturn Compos"
},
{
"path": "vendor/composer/ClassLoader.php",
"chars": 12466,
"preview": "<?php\n\n/*\n * This file is part of Composer.\n *\n * (c) Nils Adermann <naderman@naderman.de>\n * Jordi Boggiano <j.bogg"
},
{
"path": "vendor/composer/LICENSE",
"chars": 1075,
"preview": "\nCopyright (c) 2016 Nils Adermann, Jordi Boggiano\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "vendor/composer/autoload_classmap.php",
"chars": 859,
"preview": "<?php\n\n// autoload_classmap.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($ven"
},
{
"path": "vendor/composer/autoload_namespaces.php",
"chars": 417,
"preview": "<?php\n\n// autoload_namespaces.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($v"
},
{
"path": "vendor/composer/autoload_psr4.php",
"chars": 243,
"preview": "<?php\n\n// autoload_psr4.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($vendorD"
},
{
"path": "vendor/composer/autoload_real.php",
"chars": 1681,
"preview": "<?php\n\n// autoload_real.php @generated by Composer\n\nclass ComposerAutoloaderInit5b938720cfef7b7256946290ccab109b\n{\n p"
},
{
"path": "vendor/composer/autoload_static.php",
"chars": 2533,
"preview": "<?php\n\n// autoload_static.php @generated by Composer\n\nnamespace Composer\\Autoload;\n\nclass ComposerStaticInit5b938720cfef"
},
{
"path": "vendor/composer/installed.json",
"chars": 8777,
"preview": "[\n {\n \"name\": \"crodas/languagedetector\",\n \"version\": \"v0.1.1\",\n \"version_normalized\": \"0.1.1.0\","
},
{
"path": "vendor/crodas/text-rank/.travis.yml",
"chars": 168,
"preview": "language: php\nscript: phpunit tests\n\nphp:\n - 5.4\n - 5.5\n\nbefore_script:\n - php -i\n - curl -sS https://getcomposer.or"
},
{
"path": "vendor/crodas/text-rank/LICENSE",
"chars": 1490,
"preview": "Copyright (c) 2013, César D. Rodas\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
},
{
"path": "vendor/crodas/text-rank/README.md",
"chars": 1764,
"preview": "TextRank [](https://travis-ci.org/crodas/TextRan"
},
{
"path": "vendor/crodas/text-rank/composer.json",
"chars": 475,
"preview": "{\n \"name\": \"crodas/text-rank\",\n \"description\": \"Extract relevant keywords from a given text\",\n \"require\": {\n "
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Config.php",
"chars": 4090,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/DefaultEvents.php",
"chars": 3963,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/POS/English/Tagger.php",
"chars": 6478,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/POS/English/generate.php",
"chars": 329,
"preview": "<?php\n\n$fh = fopen(__DIR__ . \"/lexicon.txt\", 'r');\nwhile($line = fgets($fh)) {\n $tags = array_map('rtrim', explode(' "
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/POS/English/lexicon.php",
"chars": 4083420,
"preview": "<?php return array (\n '!' => \n array (\n 0 => '!',\n ),\n '#' => \n array (\n 0 => '#',\n ),\n '$' => \n array (\n "
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/POS/English/lexicon.txt",
"chars": 1273822,
"preview": "! !\n# #\n$ $\n% NN JJ VB SYM\n%... :\n%CHG NN\n& CC NNP SYM\n( (\n) )\n* SYM , :\n+ SYM NN\n, ,\n- :\nSamuel NNP\nYr. NN\naminometha N"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/Stopword.php",
"chars": 76145,
"preview": "<?php return array (\n 'czech' => \n array (\n 'dnes' => 1,\n 'cz' => 1,\n 'timto' => 1,\n 'budes' => 1,\n 'bu"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/czech-stopwords.txt",
"chars": 652,
"preview": "dnes\ncz\ntimto\nbudes\nbudem\nbyli\njses\nmuj\nsvym\nta\ntomto\ntohle\ntuto\ntyto\njej\nzda\nproc\nmate\ntato\nkam\ntohoto\nkdo\nkteri\nmi\nnam"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/danish-stopwords.txt",
"chars": 477,
"preview": "af\nalle\nandet\nandre\nat\nbegge\nda\nde\nden\ndenne\nder\nderes\ndet\ndette\ndig\ndin\ndog\ndu\nej\neller\nen\nend\nene\neneste\nenhver\net\nfem"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/dutch-stopwords.txt",
"chars": 177,
"preview": "aan\naf\nal\nals\nbij\ndan\ndat\ndie\ndit\neen\nen\ner\nhad\nheb\nhem\nhet\nhij\nhoe\nhun\nik\nin\nis\nje\nkan\nme\nmen\nmet\nmij\nnog\nnu\nof\nons\nook"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/english-stopwords.txt",
"chars": 961,
"preview": "a\nabout\nabove\nafter\nagain\nagainst\nall\nam\nan\nand\nany\nare\naren't\nas\nat\nbe\nbecause\nbeen\nbefore\nbeing\nbelow\nbetween\nboth\nbut"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/finnish-stopwords.txt",
"chars": 5474,
"preview": "aiemmin\naika\naikaa\naikaan\naikaisemmin\naikaisin\naikajen\naikana\naikoina\naikoo\naikovat\naina\nainakaan\nainakin\nainoa\nainoat\na"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/french-stopwords.txt",
"chars": 658,
"preview": "alors\nau\naucuns\naussi\nautre\navant\navec\navoir\nbon\ncar\nce\ncela\nces\nceux\nchaque\nci\ncomme\ncomment\ndans\ndes\ndu\ndedans\ndehors\n"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/generate.php",
"chars": 369,
"preview": "<?php\n\nforeach (glob(__DIR__ . \"/*.txt\") as $file) {\n $lang = substr(basename($file), 0, -14);\n $words = file($fi"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/german-stopwords.txt",
"chars": 7338,
"preview": "ab\nbei\nda\ndeshalb\nein\nfür\nhaben\nhier\nich\nja\nkann\nmachen\nmuesste\nnach\noder\nseid\nsonst\nund\nvom\nwann\nwenn\nwie\nzu\nbin\neines\n"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/hungarian-stopwords.txt",
"chars": 136,
"preview": "a\naz\negy\nbe\nki\nle\nfel\nmeg\nel\nát\nrá\nide \toda\nszét\nössze\nvissza\nde\nhát\nés\nvagy\nhogy\nvan\nlesz\nvolt \tcsak\nnem\nigen\nmint\nén\nt"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/italian-stopwords.txt",
"chars": 753,
"preview": "a\nadesso\nai\nal\nalla\nallo\nallora\naltre\naltri\naltro\nanche\nancora\navere\naveva\navevano\nben\nbuono\nche\nchi\ncinque\ncomprare\ncon"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/norwegian-stopwords.txt",
"chars": 576,
"preview": "alle\nandre\narbeid\nav\nbegge\nbort\nbra\nbruke\nda\ndenne\nder\nderes\ndet\ndin\ndisse\ndu\neller\nen\nene\neneste\nenhver\nenn\ner\net\nfolk\n"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/polish-stopwords.txt",
"chars": 1491,
"preview": "a\naby\nach\nacz\naczkolwiek\naj\nalbo\nale\należ\naż\nbardziej\nbardzo\nbez\nbo\nbowiem\nby\nbyli\nbynajmniej\nbyć\nbył\nbyła\nbyło\nbyły\nbęd"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/portuguese-stopwords.txt",
"chars": 849,
"preview": "último\né\nacerca\nagora\nalgmas\nalguns\nali\nambos\nantes\napontar\naquela\naquelas\naquele\naqueles\naqui\natrás\nbem\nbom\ncada\ncaminh"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/russian-stopwords.txt",
"chars": 2481,
"preview": "а\nе\nи\nж\nм\nо\nна\nне\nни\nоб\nно\nон\nмне\nмои\nмож\nона\nони\nоно\nмной\nмного\nмногочисленное\nмногочисленная\nмногочисленные\nмногочисле"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/spanish-stopwords.txt",
"chars": 1142,
"preview": "un\nuna\nunas\nunos\nuno\nsobre\ntodo\ntambién\ntras\notro\nalgún\nalguno\nalguna\nalgunos\nalgunas\nser\nes\nsoy\neres\nsomos\nsois\nestoy\ne"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/swedish-stopwords.txt",
"chars": 2371,
"preview": "aderton\nadertonde\nadjö\naldrig\nalla\nallas\nallt\nalltid\nalltså\nän\nandra\nandras\nannan\nannat\nännu\nartonde\nartonn\nåtminstone\na"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword/turkish-stopwords.txt",
"chars": 605,
"preview": "acaba\naltmýþ\naltý\nama\nbana\nbazý\nbelki\nben\nbenden\nbeni\nbenim\nbeþ\nbin\nbir\nbiri\nbirkaç\nbirkez\nbirþey\nbirþeyi\nbiz\nbizden\nbiz"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Stopword.php",
"chars": 5127,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/Summary.php",
"chars": 3901,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/SummaryPageRank.php",
"chars": 4195,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/TextRank.php",
"chars": 5534,
"preview": "<?php\n/*\n +---------------------------------------------------------------------------------+\n | Copyright (c) 2013 Cé"
},
{
"path": "vendor/crodas/text-rank/lib/TextRank/language-profile.php",
"chars": 708797,
"preview": "<?php return array (\n 'config' => \n LanguageDetector\\Config::__set_state(array(\n 'minLenNGram' => 2,\n 'maxLenN"
},
{
"path": "vendor/crodas/text-rank/phpunit.xml",
"chars": 1225,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->\n<"
},
{
"path": "vendor/crodas/text-rank/tests/QuickTest.php",
"chars": 2280,
"preview": "<?php\n\nclass QuickTest extends \\phpunit_framework_testcase\n{\n public static function provider()\n {\n return "
},
{
"path": "vendor/crodas/text-rank/tests/bootstrap.php",
"chars": 52,
"preview": "<?php\n\nrequire __DIR__ . \"/../vendor/autoload.php\";\n"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/english1.expected",
"chars": 124,
"preview": "*storing or accessing your data\n*security of your data\nAmazon\nAmazon S3\n*store customer data\n*user's data\n*data stored\nL"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/english1.summary",
"chars": 147,
"preview": "In the case of S4, the grid has one server which is run by Least Authority, and configured to store its data in Amazon S"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/english1.txt",
"chars": 6101,
"preview": "A \"storage grid\" is made up of one or more storage servers. In the case of S4, the grid has one server which is run by L"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/italian.expected",
"chars": 19,
"preview": "Brunetta\n*pensioni\n"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/italian.summary",
"chars": 281,
"preview": "Per l’economista Pd, a cui il premier Enrico Letta ha delegato la regia per la legge di Stabilità, ci saranno anche «int"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/italian.txt",
"chars": 9025,
"preview": "ROMA - Cuneo, casa e crescita. Su questi tre concetti la legge di Stabilità, che in questi giorni è in commissione al Se"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/spanish1.expected",
"chars": 105,
"preview": "drogas\nfrontera oeste\nFoz de Yguazú\nYguazú\nFrontera\nFoz\n*objetivo es el combate\narmas\n*objetivo combatir\n"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/spanish1.summary",
"chars": 245,
"preview": "El objetivo es el combate a los crímenes transfronterizos, principalmente la entrada de drogas, armas y municiones por e"
},
{
"path": "vendor/crodas/text-rank/tests/fixtures/spanish1.txt",
"chars": 937,
"preview": "El “Operativo Frontera Sur”, que se puso en marcha con alrededor de 100 militares, en la región de Foz de Yguazú, en el "
},
{
"path": "vendor/davechild/textstatistics/.travis.yml",
"chars": 313,
"preview": "language: php\nbefore_script:\n - wget http://getcomposer.org/composer.phar\n - php composer.phar install --dev\nphp:\n - "
},
{
"path": "vendor/davechild/textstatistics/LICENSE",
"chars": 1293,
"preview": "Copyright (c) 2014, Dave Child\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\n"
},
{
"path": "vendor/davechild/textstatistics/README.md",
"chars": 3161,
"preview": "#PHP Text Statistics\n\n[](https://travi"
},
{
"path": "vendor/davechild/textstatistics/composer.json",
"chars": 911,
"preview": "{\n \"name\": \"davechild/textstatistics\",\n \"description\": \"PHP package to measure the readability of text according t"
},
{
"path": "vendor/davechild/textstatistics/phpunit.xml.dist",
"chars": 277,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<phpunit\n colors=\"true\"\n bootstrap=\"./vendor/autoload.php\">\n\n <testsuit"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Maths.php",
"chars": 7456,
"preview": "<?php\n\nnamespace DaveChild\\TextStatistics;\n\nclass Maths\n{\n\n /**\n * @var boolean $blnBcmath Efficiency: Is the BC "
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Pluralise.php",
"chars": 6089,
"preview": "<?php\n\nnamespace DaveChild\\TextStatistics;\n\nclass Pluralise\n{\n /**\n * Singularising and Pluralising functions fro"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Resource.php",
"chars": 1252,
"preview": "<?php\n\nnamespace DaveChild\\TextStatistics;\n\nclass Resource\n{\n\n /**\n * Array containing the Spache word list, if s"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Syllables.php",
"chars": 13495,
"preview": "<?php\n\nnamespace DaveChild\\TextStatistics;\n\nclass Syllables\n{\n\n // Specific common exceptions that don't follow the r"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/Text.php",
"chars": 10635,
"preview": "<?php\n\nnamespace DaveChild\\TextStatistics;\n\nclass Text\n{\n\n /**\n * @var boolean $blnMbstring Efficiency: Is the MB"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/TextStatistics.php",
"chars": 18469,
"preview": "<?php\n\nnamespace DaveChild\\TextStatistics;\n\n/*\n\n TextStatistics Project\n https://github.com/DaveChild/Text-Statist"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/resources/DaleChallWordList.php",
"chars": 42344,
"preview": "<?php\r\n\r\n$arrDaleChallWordList = Array(\r\n 'a'\r\n ,'able'\r\n ,'aboard'\r\n ,'about'\r\n ,'above'\r\n ,'absent'"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/resources/Homographs.txt",
"chars": 249,
"preview": "Homographs which have different syllables depending upon their meaning.\n\nagape\naged\nblessed\ncoax\ncoop\ncrooked\ncube\ndenie"
},
{
"path": "vendor/davechild/textstatistics/src/DaveChild/TextStatistics/resources/SpacheWordList.php",
"chars": 14543,
"preview": "<?php\r\n\r\n$arrSpacheWordList = Array(\r\n 'a'\r\n ,'able'\r\n ,'about'\r\n ,'above'\r\n ,'across'\r\n ,'act'\r\n "
},
{
"path": "vendor/davechild/textstatistics/tests/TextStatisticsCMULexTest.php",
"chars": 864138,
"preview": "<?php\n\nclass TextStatisticsTestCMULex extends PHPUnit_Framework_TestCase\n{\n\n /*\n\n Words failing according to t"
},
{
"path": "vendor/davechild/textstatistics/tests/TextStatisticsKiplingIfTest.php",
"chars": 30565,
"preview": "<?php\n\nclass TextStatisticsKiplingIf extends PHPUnit_Framework_TestCase\n{\n\n /*\n\n Text\n ----------------"
},
{
"path": "vendor/davechild/textstatistics/tests/TextStatisticsMaths.php",
"chars": 12442,
"preview": "<?php\n\nclass TextStatisticsMaths extends PHPUnit_Framework_TestCase\n{\n\n /*\n\n This file contains the more basic"
},
{
"path": "vendor/davechild/textstatistics/tests/TextStatisticsMelvilleMobyDickTest.php",
"chars": 22493,
"preview": "<?php\n\nclass TextStatisticsMelvilleMobyDick extends PHPUnit_Framework_TestCase\n{\n\n /*\n\n Text\n ---------"
},
{
"path": "vendor/davechild/textstatistics/tests/TextStatisticsPluralise.php",
"chars": 3096,
"preview": "<?php\n\nclass TextStatisticsPluralise extends PHPUnit_Framework_TestCase\n{\n\n /*\n\n This file contains the more b"
},
{
"path": "vendor/davechild/textstatistics/tests/TextStatisticsTest.php",
"chars": 24587,
"preview": "<?php\n\nclass TextStatisticsTest extends PHPUnit_Framework_TestCase\n{\n\n /*\n\n This file contains the more basic "
},
{
"path": "vendor/sunra/php-simple-html-dom-parser/README.md",
"chars": 685,
"preview": "php-simple-html-dom-parser\n==========================\n\nVersion 1.5\n\nAdaptation for Composer and PSR-0 of:\n\nA HTML DOM pa"
},
{
"path": "vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php",
"chars": 562,
"preview": "<?php\r\n\r\nnamespace Sunra\\PhpSimple;\r\n\r\nrequire 'simplehtmldom_1_5'.DIRECTORY_SEPARATOR.'simple_html_dom.php';\r\n\r\nclass H"
},
{
"path": "vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/change_log.txt",
"chars": 4539,
"preview": "#$Rev: 194 $\n[Updates - add some ability to insert and create nodes.]\n[1: add ability to search the \"noise\" array]\n\n[PHP"
},
{
"path": "vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/simple_html_dom.php",
"chars": 63705,
"preview": "<?php\n\nnamespace simplehtmldom_1_5;\n\n/**\n * Website: http://sourceforge.net/projects/simplehtmldom/\n * Acknowledge: Jose"
},
{
"path": "vendor/sunra/php-simple-html-dom-parser/composer.json",
"chars": 903,
"preview": "{\n \"name\": \"sunra/php-simple-html-dom-parser\",\n \"type\": \"library\",\n \"description\": \"Composer adaptation of: A H"
}
]
About this extraction
This page contains the full source code of the nystudio107/seomatic GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 182 files (8.0 MB), approximately 2.1M tokens, and a symbol index with 556 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.