Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

User1980's avatar

How do you deal with Seo when using Vue with Laravel(SPA)

Hello,

I would like to know how do you usually deal with meta tags in a vue app when hooking it up to Laravel please. I do not build SPA and would like to start, but I am really no sure how this will affect Seo as a whole.

I would love to hear some feedback from experienced users on this please.

Thanks!

0 likes
9 replies
User1980's avatar

@lolsokje Thanks for that. I am wondering if this is why Alpine.js is doing well at the moment. It looks like SSR is not an easy thing to setup and again add overheads to the development :-(

martinbean's avatar

@User1980 Well, choosing to put the app on the client is going to make things like SEO difficult. Yes, you can use server-side rendering, but then this to me just feels like solving a problem you’ve caused yourself by choosing to build a SPA.

2 likes
User1980's avatar

@martinbean Thanks Martin, I came back to the old NON-SPA method, I found the SPA setup too difficult/overwhelming. Thanks for your input and you are right, by doing this, I was going to cause myself a problem to start with.

drehimself's avatar

When I have to build a SPA with Vue + Laravel, I usually think of these two options:

1...Can I get away with using Inertia. If I only need a web app (and I don't need another client like a mobile app), using Inertia (for me) is just so much easier to work with. You mostly do things the "traditional" Laravel way and you're just replacing your blade views with Vue components.

Also, Inertia just released Server Side Rendering publically so your pages can now be rendered on the server making everything more SEO friendly: https://inertiajs.com/server-side-rendering. There's also options for title and meta tags like you mentioned: https://inertiajs.com/title-and-meta

2...If the requirements say that I need to build a traditional SPA with API routes (say for multiple clients), I would go with Nuxt for the web framework. It does SSR for Vue and adds a bunch of nice features like automatic routing with files.

2 likes
User1980's avatar

@drehimself Thank you so much for the explanation. Today I tried to get Inertia going with vue via SSR...I found it overcomplicated and had to give up on it. I came back to the old vue/laravel/tailwind non SPA to move faster with my project. I like to work on projects which require a less difficult set-up so I do not get confused when something stops working and can also pass the project onto someone else easily. The intertia SSR setup was just too complicated and I could not understand what was happening while setting it up.

1 like
JackPetty's avatar

SEO in the context of Vue with Laravel can be a bit tricky, but it's definitely doable. When it comes to handling meta tags for your Vue app integrated with Laravel, you'll want to use server-side rendering (SSR) to ensure that search engines can crawl and index your content effectively. This helps maintain good SEO practices.As for experienced users, I'd recommend reaching out to the experts at Digital Marketing Agency Los Angeles. They have a wealth of knowledge and experience in the field, and they can provide you with valuable insights and guidance on optimizing your Vue and Laravel setup for SEO.

Smash's avatar

I kinda evolved into a bit of a system for this problem. I needed not just SSR - but I needed a true unchanging meta title/description from first response to full takeover by vue on the client side for all pages that aren't requiring authentication.

So here's how it works (Using Laravel Jetstream in this example) - for any fellow keep it vue-ers:

First off is a ./config/metadata.php file:

Next up, is a custom Helper ./app/Helpers/Metadata.php class file:

And with those pieces, we can hop over to the ./app/Http/Middleware/HandleInertiaRequests.php file, and update the share() method with our new stuff:

use App\Helpers\Metadata;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        Metadata::handleJetstreamInertiaRequests($request);

        return [
            ...parent::share($request),
            'ziggy' => fn () => [
                ...(new Ziggy)->toArray(),
                'location' => $request->url(),
            ],
            'metadata' => fn () => config('metadata'),
        ];
    }
}

Now moving on to a Controller for a page, here's a ./app/Http/Controllers/DashboardController.php class file:

use App\Helpers\Metadata;
use Inertia\Inertia;
use Inertia\Response;

class DashboardController extends Controller
{
    /**
     * Display the view.
     */
    public function index(): Response
    {
        Metadata::addTitlesAndDescriptions(
            config('metadata.titles.dashboard'),
            config('metadata.descriptions.dashboard')
        );

        return Inertia::render( 'Dashboard', [
           // "some_data" => "",
        ]);
    }
}

And nearing the finish line, the app's core blade base file then looks something like this:

And last but not least, in a final Vue sense, it's a good idea to bake this common scenario into a layout component. So the Jetstream ./resources/js/Layouts/AppLayout.vue file might look like this:

The above referenced ./resources/js/Components/metadata/HeadMetadata.vue file looks like this:

And to finally wrap everything together in a ./resources/js/Pages/Dashboard.vue page file, would look something like this:

<script setup lang="ts">

    import { computed } from 'vue'
    import { usePage } from '@inertiajs/vue3'

    import AppLayout from '../Layouts/AppLayout.vue'

    const pageProps = computed( () => usePage().props )

</script>

<template>

    <AppLayout
        :title="pageProps.metadata.titles.dashboard"
        :description="pageProps.metadata.descriptions.dashboard"
    >

        	<!-- Awesome app with smashing SEO goes here! -->

    </AppLayout>

</template>

Thank you for coming to my DEV talk. Hope this helps someone. Might add it into my VILT-DS lib, because once it's wired up, it's kinda awesome. In VILT-DS, I could just add it to the install scripts. Then this would be ready out of the box!

This approach pushes the SEO data down from the PHP side via the blade file, then matches the data in the client side via Vue via Inertia. What's cool is you can even process data, for a meta title with a specific name in it for example, then push that down as metadata from PHP like normal, but now modify the config in the response with a new one that overrides the value for the specifically named page in the config data that's normally just dumped down to the client from the HandleInertiaRequests injection of the metadata config earlier in the request.

So it's seamless SEO, even for dynamic db pages. It works with and without SSR, but obviously SSR is better as it sends down the correct markup before Vue takes over. SSR and this approach together though... are all the control I could ever need for a product or client.

But after putting all this here, it's way more involved than I realized. fml.

Please or to participate in this conversation.