Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Opengraph Laravel Package

apility/opengraph

A Laravel package for fetching and parsing Open Graph metadata from URLs, letting you extract titles, descriptions, images, and other page preview data for link cards and rich embeds.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer and, if the package ships one, publish its config so defaults (site name, fallback image, locale, Twitter handle) live in config/ rather than being re-typed in every controller:

composer require <vendor>/<package>
php artisan vendor:publish --tag=<package>-config

First place to look is the OpenGraph class itself — it is the whole API surface. v1.0.4 adds containsProperty(), so any code you write should treat the class as a small queryable collection of meta tags rather than a write-only builder: you can now ask what is already set before deciding what to add.

The first real use case is a layout head partial. Put a single @include('partials.meta') (or a Blade component) in your layouts/app.blade.php <head>, set sensible defaults from config, and let individual pages push overrides from their controller or from the view itself. That keeps one rendering path for Open Graph and — as of this release — Twitter cards.

// in the layout/head partial
{!! OpenGraph::render() !!}

The v1.0.4 release is additive: new Twitter card meta tags are emitted alongside the Open Graph ones, and containsProperty() is a read-only helper. Nothing here forces you to change existing calls, so upgrading is a composer update away.

Implementation Patterns

Defaults-then-overrides. Set site-wide values once (site name, type, default share image, Twitter @handle) at boot — a service provider, a base controller constructor, or a view composer — then let each page add or replace only what differs. Everything downstream reads consistently and pages stay short.

Guard against duplicate tags with containsProperty(). This is the main reason to reach for the new method. Instead of tracking state yourself, ask before writing:

if (! OpenGraph::containsProperty('og:image')) {
    OpenGraph::addProperty('og:image', asset('img/default-share.png'));
}

That pattern belongs in the head partial or a middleware so it runs after the controller has had a chance to set a page-specific image — order matters, so render late in the request lifecycle.

Blog/show pages are the canonical case. A Post show action sets og:title, og:description, og:image, og:type = article, plus article-specific properties. Index and static pages fall through to the defaults, which is exactly what the guard above is for.

Twitter cards pair with Open Graph, they don't replace it. Twitter/X falls back to og:* tags when twitter:* tags are missing, so adding Twitter tags is mostly about precision: set twitter:card to summary_large_image when you want the wide image, and give it an explicit twitter:image for cases where the OG image is the wrong crop. Because the package now emits these, you should delete any hand-rolled twitter:* lines from your Blade templates to avoid emitting them twice.

Set from the controller, not the template, when the data is domain data. Passing a model into the Open Graph builder in a controller keeps views dumb and makes the head partial reusable across layouts. Template-level calls are fine for purely presentational overrides (a hero image chosen in the view).

Centralise absolute URLs. Every og:image / twitter:image must be absolute. Use asset() or a URL accessor on the model, and if you store uploads on S3 or a CDN, make sure the disk's url config is correct — otherwise you ship tags pointing at localhost.

Assert it in tests. A quick feature test on your head partial (assert the response contains og:image, twitter:card, and no duplicated og:title) catches regressions cheaply, especially once you have conditional logic built on containsProperty().

Gotchas and Tips

  • Ordering and the guard. containsProperty() only knows about tags added before it runs. If you call it in a middleware but set the page image in the controller afterwards, the guard is meaningless. Decide on one lifecycle point (usually the head partial, rendered last) and stick to it.

  • Duplicate tags are silent. Browsers and most crawlers take the first or last occurrence of a duplicated og:title — behaviour varies — and nothing will warn you. After adding Twitter tags, grep your templates for any leftover twitter: strings from the pre-v1.0.4 workaround.

  • twitter:card is not optional in practice. Without it, X renders a plain link even when og:* tags are perfect. If sharing looks broken on X only, check this value before debugging images.

  • Image dimensions. For summary_large_image, a 1.91:1 image around 1200×630 renders correctly; square-ish images get cropped or fall back to a small card. You can state og:image:width / og:image:height explicitly, but Twitter mostly ignores them — crop the asset itself.

  • Caching and fragments. If you cache the rendered head partial or use response caching, per-page tags will be served to the wrong pages. Key the cache on the model/page, or render the head after cache retrieval.

  • Escaping. Meta content attributes must be escaped; descriptions containing quotes or accents break the tag if you concatenate raw strings. Confirm your rendering path escapes, and strip/limit description length (roughly 150–200 characters) since both Facebook and X truncate.

  • Relative URLs are the #1 cause of "no preview image". Crawlers do not resolve relative paths reliably. Always asset().

  • Version pinning. You are on 1.0.x; the API is stabilising but still young. Pin to ^1.0 and read the changelog on each patch — v1.0.4 was purely additive, but small pre-2.0 packages occasionally adjust signatures.

  • Extension point. If the tag set does not cover something (custom namespaces, JSON-LD), do not fork the class — add a small dedicated partial next to the package's rendered output. Keep the package responsible for OG/Twitter tags only, so future upgrades stay trivial.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource