{"id":20961907,"url":"https://github.com/heimrichhannot/contao-head-bundle","last_synced_at":"2025-09-04T18:48:45.672Z","repository":{"id":25125140,"uuid":"103108463","full_name":"heimrichhannot/contao-head-bundle","owner":"heimrichhannot","description":"Add \u003chead\u003e tags, like seo meta tags or twitter cards, or open graph meta tags to contao frontend page.","archived":false,"fork":false,"pushed_at":"2025-04-10T15:53:39.000Z","size":373,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-02T02:27:16.917Z","etag":null,"topics":["contao","php","seo"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/heimrichhannot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-09-11T08:14:49.000Z","updated_at":"2025-04-10T15:50:27.000Z","dependencies_parsed_at":"2025-05-14T07:35:42.488Z","dependency_job_id":"3b22596e-5663-4118-8492-aa885178dbd5","html_url":"https://github.com/heimrichhannot/contao-head-bundle","commit_stats":{"total_commits":97,"total_committers":6,"mean_commits":"16.166666666666668","dds":0.5979381443298969,"last_synced_commit":"520bcf2c6e3c2ed6accdf1cd9e54dded382dfae1"},"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"purl":"pkg:github/heimrichhannot/contao-head-bundle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-head-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-head-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-head-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-head-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/heimrichhannot","download_url":"https://codeload.github.com/heimrichhannot/contao-head-bundle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-head-bundle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273363915,"owners_count":25092272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contao","php","seo"],"created_at":"2024-11-19T02:18:30.618Z","updated_at":"2025-09-04T18:48:45.615Z","avatar_url":"https://github.com/heimrichhannot.png","language":"PHP","readme":"# Contao Head bundle\n\n[![](https://img.shields.io/packagist/v/heimrichhannot/contao-head-bundle.svg)](https://packagist.org/packages/heimrichhannot/contao-head-bundle)\n[![](https://img.shields.io/packagist/dt/heimrichhannot/contao-head-bundle.svg)](https://packagist.org/packages/heimrichhannot/contao-head-bundle)\n\nThis bundle enhances the handling of html `\u003chead\u003e` section tags. It provides services to update head tags dynamically from your code.\n\n## Features\n- Provide a nice api to set head tags like meta, title, base, link\n- Provide additional json-ld schema data\n- Sets important meta tags like og:title, og:description, og:url and twitter:card out of the box\n- Allow setting open graph and twitter fallback image on root page\n- Allow setting twitter author per root page\n- Backport canonical url option from contao 4.13 for contao 4.9+\n- Backport json-ld support for contao 4.9+\n\n## Usage\n\n### Setup\n\n1. Install with composer\n2. Update your database\n3. Set following config variables (if you don't need the legacy implementation)\n\n    ```yaml\n    huh_head:\n      use_contao_head: true\n      use_contao_variables: true\n    ```\n4. Optional: Set fallback image and twitter author in root page(s)\n\n### Add additional meta tags\n\nIn your root page, you can activate to add fallback image (og:image and twitter:image) and twitter username (twitter:site) meta tags to you web page.\n\n![Screenshot Meta Data Settings](docs%2Fimg%2Fscreenshot_backend_meta_data.png)\n\n### Add additional schema.org data\n\nIn your root page, you can activate to add additional structured data to you web page.\nFollowing schema.org types are available:\n* @Organization\n* @WebSite\n* @WebPage\n* @BreadcrumbList\n\n\n![Screenshot Structured Data Settings](docs%2Fimg%2Fscreenshot_backend_structured_data.png)\n\n### Set json-ld in your templates\n\nThis bundle backports the methods of contao 4.12+ to contao 4.9+. So usage is the same as in the contao core.\n\n#### Twig templates\n\n```twig\n{% do add_schema_org({\n    '@type': 'NewsArticle',\n    'headline': newsHeadline|striptags,\n    'datePublished': datetime|date('Y-m-d\\TH:i:sP'),\n}) %}\n```\n\n#### PHP templates\n\n```php\n\u003c?php $this-\u003eaddSchemaOrg([\n    '@type' =\u003e 'NewsArticle',\n    'headline' =\u003e $newsHeadline,\n    'datePublished' =\u003e $datetime-\u003edate('Y-m-d\\TH:i:sP'),\n]); ?\u003e\n```\n\n\n## Integration\nUse head bundle api set in your code.\n\n### Set head content\n\nTo set base, title, meta and link tags, use the `HtmlHeadTagManager` service:\n\n```php\nuse HeimrichHannot\\HeadBundle\\HeadTag\\BaseTag;\nuse HeimrichHannot\\HeadBundle\\HeadTag\\MetaTag;\nuse HeimrichHannot\\HeadBundle\\HeadTag\\TitleTag;\nuse HeimrichHannot\\HeadBundle\\HeadTag\\Meta\\CharsetMetaTag;\nuse HeimrichHannot\\HeadBundle\\HeadTag\\Meta\\HttpEquivMetaTag;\nuse HeimrichHannot\\HeadBundle\\HeadTag\\Meta\\PropertyMetaTag;\nuse HeimrichHannot\\HeadBundle\\Manager\\HtmlHeadTagManager;\nuse Symfony\\Component\\HttpFoundation\\Request;\n\nclass SomeEventListener\n{\n    private HtmlHeadTagManager $headTagManager;\n\n    public function updateBaseTag(Request $request): void\n    {\n        // Set base tag to null to remove it\n        $this-\u003eheadTagManager-\u003esetBaseTag(null);\n        \n        //Set base tag from object or url\n        $this-\u003eheadTagManager-\u003esetBaseTag(new BaseTag($request-\u003egetSchemeAndHttpHost()));\n        $this-\u003eheadTagManager-\u003esetBaseTag('https://example.org'));\n    }\n    \n    public function updatedTitleTag(): void\n    {\n        // Set title to \"Hello World\"\n        $this-\u003eheadTagManager-\u003esetTitleTag('Hello World');\n        \n        // Set title tag from object and adjust output format\n        $this-\u003eheadTagManager-\u003esetTitleTag(new TitleTag('Foo Bar', '%s | {{page::rootPageTitle}}'))\n        // Will output: \u003ctitle\u003eFoo Bar | My Great Website Page Title\u003c/title\u003e\n    }\n    \n    public function setMetaTags(): void\n    {\n        // Add a new meta tag. If a tag with the same name already exists, it will be overridden\n        $this-\u003eheadTagManager-\u003eaddMetaTag(new MetaTag('author', 'John Doe'));\n        \n        // Get an existing tag\n        $description = ($tag = $this-\u003eheadTagManager-\u003egetMetaTag('og:description')) ? $tag-\u003egetContent() : '';\n        \n        // Remove a tag\n        $this-\u003eheadTagManager-\u003eremoveMetaTag('twitter:site');\n        \n        // Create a tag for property meta tags\n        $this-\u003eheadTagManager-\u003eaddMetaTag(new PropertyMetaTag('og:type', 'article'));\n        \n        // Create a http-equiv tag\n        $this-\u003eheadTagManager-\u003eaddMetaTag(new HttpEquivMetaTag('refresh', '30'));\n        \n        // Set a charset tag\n        $this-\u003eheadTagManager-\u003eaddMetaTag(new CharsetMetaTag('UTF-8'));\n        \n        // Create tags without class (usefull when creating tags in a loop without custom checks)\n        $this-\u003eheadTagManager-\u003eaddMetaTag(\n            $this-\u003eheadTagManager-\u003egetHeadTagFactory()-\u003ecreateMetaTag('description', 'Lorem ipsum!')\n        );\n        $this-\u003eheadTagManager-\u003eaddMetaTag(\n            $this-\u003eheadTagManager-\u003egetHeadTagFactory()-\u003ecreateTagByName('meta_og:url', 'https://example.org')\n        );\n    }\n    \n    public function setLinkTags(): void\n    {\n        // Add a new link tag. If a tag with the same name already exists, it will be overridden\n        $this-\u003eheadTagManager-\u003eaddLinkTag(new LinkTag('next', 'https://example.org?page=2'));\n        \n        // Get an existing tag\n        $this-\u003eheadTagManager-\u003egetLinkTag('prev');\n        \n        // Remove a tag\n        $this-\u003eheadTagManager-\u003eremoveLinkTag('prev');\n        \n        // Shorthand for canonical tag\n        $this-\u003eheadTagManager-\u003esetCanonical('https://example.org');\n    }\n}\n```\n\n### Set json-ld schema data\n\n\u003e From contao 4.12 you can use the JsonLdManager service [from the core](https://docs.contao.org/dev/framework/response-context/#the-jsonldmanager).\n\nTo set json-ld schema data, use the `JsonLdManager` service:\n\n```php\n\u003c?php\nuse HeimrichHannot\\HeadBundle\\Manager\\JsonLdManager;\n\nclass ExampleController \n{\n   private JsonLdManager      $jsonLdManager;\n\n   public function __invoke() {\n      $organisation = $this-\u003ejsonLdManager-\u003egetGraphForSchema(JsonLdManager::SCHEMA_ORG)-\u003eorganization();\n      $organisation-\u003ename('Example and Sons Ltd.');\n      $organisation-\u003eurl('https://example.org');\n   }\n}\n```\n### Reader Config Contao sample\n![image](https://github.com/heimrichhannot/contao-head-bundle/assets/51906753/a5e30fdc-66f9-419a-a5a4-1805bb66b227)\n\n\n\n## Legacy integration\n\nBe sure, `huh_head.use_contao_head` and/or `huh_head.use_contao_variables` are not set to true.\n\nOutput `$this-\u003emeta()` in your fe_page template ()\n\n```\n\u003c?php $this-\u003eblock('meta'); ?\u003e\n    \u003c?= $this-\u003emeta(); ?\u003e\n\u003c?php $this-\u003eendblock(); ?\u003e\n```\n\nMake sure, that you remove (are outputted by $this-\u003emeta() if `huh_head.use_contao_head` is not true):\n\n```\n\u003cmeta charset=\"\u003c?= $this-\u003echarset ?\u003e\"\u003e\n\u003ctitle\u003e\u003c?= $this-\u003etitle ?\u003e\u003c/title\u003e\n\u003cbase href=\"\u003c?php echo $this-\u003ebase; ?\u003e\"\u003e\n\u003cmeta name=\"robots\" content=\"\u003c?= $this-\u003erobots ?\u003e\"\u003e\n\u003cmeta name=\"description\" content=\"\u003c?= $this-\u003edescription ?\u003e\"\u003e\n```\n\nThe `meta` function accepts currently one parameter that can contain service names (array) that should be skipped.\n\n## Developers\n\n### Backend field\n\nGet tag options for a select field. If you want to define options by your own, prepend meta tag options with `meta_`.\n\n```php\nuse HeimrichHannot\\HeadBundle\\Helper\\DcaHelper;\n\nclass HeadTagOptionsListener {\n    private DcaHelper $dcaHelper;\n\n    public function __invoke() {\n        return $this-\u003edcaHelper-\u003egetTagOptions([\n            // filter: (array|null) If set, only tags fulfill given filters will be returned. See FILTER constants for available options. Default null\n            'filter' =\u003e [DcaHelper::FILTER_META, DcaHelper::FILTER_TITLE],\n            // skip_tags: (array) Skip specific tags. Default empty\n            'skip_tag' =\u003e ['og:locale'],\n        ]);\n    }\n}\n```\n\nExample how to evaluate field values:\n\n```php\nuse Contao\\ContentModel;\nuse HeimrichHannot\\HeadBundle\\Manager\\HtmlHeadTagManager;\n\nclass SomeEventListener {\n    private HtmlHeadTagManager $headTagManager;\n    \n    public function __invoke(ContentModel $contentModel){\n        $tag = $this-\u003eheadTagManager-\u003egetHeadTagFactory()-\u003ecreateTagByName($contentModel-\u003eheadTag);\n        if ($tag) {\n            $tag-\u003esetAttribute(\"content\", $contentModel-\u003eheadTagContent);\n            $this-\u003eheadTagManager-\u003eaddTag($tag);\n        }\n    }\n}\n```\n\n## Config reference\n\n```yaml\n# Default configuration for extension with alias: \"huh_head\"\nhuh_head:\n\n    # Use the default head variables for title,base,robots and description instead of removing them from the page template.\n    use_contao_head:      false\n\n    # Use the default contao template variables for outputting head tags instead of the meta function.\n    use_contao_variables: false\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheimrichhannot%2Fcontao-head-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fheimrichhannot%2Fcontao-head-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheimrichhannot%2Fcontao-head-bundle/lists"}