Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

SEO for Laravel Sites Complete Setup

By Kokil Thapa | Last reviewed: August 2026

Achieving a reliable SEO for Laravel sites complete setup requires integrating metadata management, XML sitemaps, structured data, and performance optimization directly into your application architecture rather than treating them as afterthoughts. Unlike WordPress, Laravel provides no built-in SEO interface, so you must deliberately wire these systems during development to avoid indexation failures and poor rankings. This guide covers the exact configuration I use on production legal-tech portals and eCommerce platforms, linking to foundational concepts in my on-page SEO checklist for Nepal where relevant.

How Do You Configure Meta Tags and Open Graph in Laravel?

Dynamic meta tags are the foundation of any SEO for Laravel sites complete setup. Hardcoding titles and descriptions in Blade templates creates maintenance nightmares and duplicate content risks when routes share layouts. The artesaos/seotools package (v1.x for Laravel 12) provides a service-based approach that integrates cleanly with controllers and middleware.

Installation and Base Configuration

composer require artesaos/seotools

php artisan vendor:publish --provider="Artesaos\SEOTools\Providers\SEOToolsServiceProvider"

In config/seotools.php, set sensible defaults that apply site-wide while allowing per-route overrides:

'defaults' => [
    'title'       => 'Nepal Legal Services | Court Marriage & Notary',
    'description' => 'Expert legal guidance for court marriage, divorce, and notary services in Nepal.',
    'separator'   => ' - ',
    'keywords'    => ['nepal lawyer', 'court marriage nepal', 'notary kathmandu'],
    'open_graph'  => [
        'type'        => 'website',
        'site_name'   => 'Court Marriage In Nepal',
        'locale'      => 'en_US',
    ],
],

Controller-Level Metadata Assignment

Set metadata in controllers, not views. This keeps SEO logic testable and co-located with business logic:

use Artesaos\SEOTools\Facades\SEOMeta;
use Artesaos\SEOTools\Facades\OpenGraph;

public function show(string $slug)
{
    $service = Service::where('slug', $slug)->firstOrFail();

    SEOMeta::setTitle($service->meta_title ?? $service->name);
    SEOMeta::setDescription($service->meta_description ?? Str::limit($service->body, 155));
    SEOMeta::addKeyword([$service->category->name, 'nepal legal service']);
    SEOMeta::setCanonical(route('services.show', $service->slug));

    OpenGraph::setTitle($service->name);
    OpenGraph::setDescription($service->meta_description);
    OpenGraph::addImage($service->featured_image_url);
    OpenGraph::setType('article');

    return view('services.show', compact('service'));
}

In your master Blade layout, render tags once in the <head>:

<head>
    {!! SEOMeta::generate() !!}
    {!! OpenGraph::generate() !!}
</head>

This pattern prevents missing or duplicate tags across hundreds of routes. On a recent legal portal project, this eliminated 47 duplicate-title warnings within two weeks of deployment.

ControllerSEOMeta::setTitle()SEO ServiceStore + Merge DefaultsBlade Layout{!! SEOMeta::generate() !!}Browser / Crawler<title>, <meta>, OGFallback Chain: Route Meta → Model Field → Config DefaultsPrevents empty tags when content is missing
Metadata flows from controller through SEO service to rendered HTML with automatic fallbacks

How Do You Generate and Maintain XML Sitemaps Automatically?

Sitemaps are non-negotiable for indexation. Manual sitemap files break the moment you add content. Use spatie/laravel-sitemap (v7.x) to generate sitemaps dynamically or via scheduled commands.

Static Sitemap Generation via Artisan

For most Laravel applications, static generation on deploy or schedule is safer than dynamic rendering:

composer require spatie/laravel-sitemap

Create app/Console/Commands/GenerateSitemap.php:

use Spatie\Sitemap\SitemapGenerator;

class GenerateSitemap extends Command
{
    protected $signature = 'sitemap:generate';

    public function handle(): void
    {
        SitemapGenerator::create(config('app.url'))
            ->writeToFile(public_path('sitemap.xml'));

        $this->info('Sitemap generated successfully.');
    }
}

Register in routes/console.php or scheduler to run after every deployment:

Schedule::command('sitemap:generate')->daily()->at('03:00');

Custom URLs for Dynamic Content

Crawlers won't discover filtered pages, paginated archives, or user-generated profiles automatically. Add them explicitly:

use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;

$sitemap = Sitemap::create();

Service::chunk(100, function ($services) use ($sitemap) {
    foreach ($services as $service) {
        $sitemap->add(
            Url::create(route('services.show', $service->slug))
                ->setLastModificationDate($service->updated_at)
                ->setChangeFrequency(Url::CHANGE_FREQUENCY_WEEKLY)
                ->setPriority(0.8)
        );
    }
});

$sitemap->writeToFile(public_path('sitemap.xml'));

On high-traffic sites, chunk queries to avoid memory exhaustion. I've seen sitemap generation crash servers processing 50k+ records without chunking — always paginate.

How Do You Implement Schema Markup for Rich Results?

Structured data drives rich snippets, knowledge panels, and enhanced SERP features. For legal-tech and service businesses, LegalService, Attorney, and FAQPage schemas are particularly valuable. Never rely on plugins that inject generic schema — craft it per entity.

JSON-LD in Blade Templates

Output schema as inline JSON-LD in the <head>. Create a reusable component:

// resources/views/components/schema/legal-service.blade.php
@props(['service'])

<script type="application/ld+json">
{!! json_encode([
    '@context' => 'https://schema.org',
    '@type' => 'LegalService',
    'name' => $service->name,
    'description' => $service->meta_description,
    'url' => route('services.show', $service->slug),
    'telephone' => config('business.phone'),
    'address' => [
        '@type' => 'PostalAddress',
        'streetAddress' => config('business.address'),
        'addressLocality' => 'Kathmandu',
        'addressCountry' => 'NP',
    ],
    'priceRange' => 'Rs 5000-50000',
    'openingHoursSpecification' => [[
        '@type' => 'OpeningHoursSpecification',
        'dayOfWeek' => ['Monday','Tuesday','Wednesday','Thursday','Friday'],
        'opens' => '10:00',
        'closes' => '17:00',
    ]],
], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) !!}
</script>

Validate every schema output with Google's Rich Results Test before deploying. Invalid JSON-LD silently fails and wastes implementation effort.

LegalService SchemaLaw firms, notary, court marriageaddress, hours, priceRangeProduct SchemaeCommerce, gift cards, bookingsprice, availability, reviewsFAQPage SchemaService FAQs, process guidesquestion, acceptedAnswerCommon MistakesMissing @context • Invalid date formats • Nested objects without @type • Unescaped quotes in JSONAlways validate at search.google.com/test/rich-results before deploy
Three essential schema types for Laravel applications with common validation pitfalls

How Do You Optimize Core Web Vitals in Laravel 12?

Google uses Core Web Vitals as ranking signals. Laravel applications often fail LCP and CLS due to unoptimized asset pipelines and layout shifts. Address these systematically.

Vite Asset Optimization

Laravel 12 ships with Vite 6.x by default. Configure critical CSS inlining and code splitting:

// vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
    ],
    build: {
        cssCodeSplit: true,
        rollupOptions: {
            output: {
                manualChunks: {
                    vendor: ['vue', 'alpinejs'],
                },
            },
        },
    },
});

In production, preload critical assets in your layout:

@vite(['resources/css/app.css', 'resources/js/app.js'])
<link rel="preload" as="style" href="{{ Vite::asset('resources/css/critical.css') }}">

Eliminating Layout Shifts

CLS kills rankings. Reserve space for images, ads, and dynamic content:

  • Always set explicit width and height attributes on <img> tags
  • Use CSS aspect-ratio for responsive containers
  • Avoid injecting content above existing DOM elements after load
  • Font-display: swap with size-adjust to prevent FOUT shifts

On an eCommerce project, fixing image dimensions alone improved CLS from 0.42 to 0.03. Measure with Lighthouse CI in your pipeline — don't guess.

MetricTarget (2026)Laravel FixValidation Tool
LCP≤ 2.5sPreload hero image, server-side render above-fold contentPageSpeed Insights
INP≤ 200msDefer non-critical JS, use Alpine/Livewire over heavy frameworksChrome DevTools
CLS≤ 0.1Explicit image dimensions, font-display: swap, reserved ad slotsLighthouse CI

How Do You Handle Canonical URLs and Duplicate Content?

Duplicate content destroys crawl budget and dilutes ranking signals. Laravel applications create duplicates through pagination, filters, sorting parameters, and HTTP/HTTPS variants.

Canonical Tag Strategy

Set canonicals explicitly on every page. Never assume Laravel's URL helper produces the correct canonical:

// In controller or middleware
SEOMeta::setCanonical(route('services.show', ['slug' => $service->slug]));

// For paginated pages, canonical points to page 1 unless intentional
if ($page > 1) {
    SEOMeta::setCanonical(route('services.index'));
}

// Strip tracking params from canonical
$cleanUrl = request()->url(); // Excludes query string
SEOMeta::setCanonical($cleanUrl);

Robots and Noindex Directives

Block crawlers from low-value pages programmatically:

// Middleware or controller
if (request()->has('sort') || request()->has('filter')) {
    SEOMeta::setRobots('noindex, follow');
}

// Admin, preview, and staging routes
Route::middleware('auth')->group(function () {
    // These should never be indexed
});

Generate robots.txt dynamically to reflect environment:

// routes/web.php
Route::get('/robots.txt', function () {
    if (app()->environment('production')) {
        return response("User-agent: *\nAllow: /\nSitemap: " . url('/sitemap.xml'), 200)
            ->header('Content-Type', 'text/plain');
    }
    return response("User-agent: *\nDisallow: /", 200)
        ->header('Content-Type', 'text/plain');
});
Incoming RequestHas sort/filter params?→ noindex, followPaginated page > 1?→ canonical to page 1Unique content page?→ self-canonicalAlways verify canonical output in view-source before indexingGoogle Search Console → URL Inspection → View Tested Page → Check <link rel="canonical">
Decision tree for setting canonical and robots directives based on route characteristics

What Monitoring and Validation Workflow Prevents SEO Regressions?

SEO breaks silently. Establish automated checks before they impact traffic. For teams managing multiple Laravel properties, understanding SEO service pricing in Nepal helps budget for ongoing monitoring versus one-time fixes.

Pre-Deploy Validation Checklist

  1. Run php artisan sitemap:generate and diff against previous version
  2. Validate JSON-LD with google/rich-results-test CLI or API
  3. Lighthouse CI threshold gates in GitLab/GitHub Actions
  4. Check meta tag presence on sample routes via HTTP test
  5. Verify robots.txt returns correct directives for environment

Post-Launch Monitoring

Connect Google Search Console immediately. Monitor:

  • Coverage report for crawl errors and excluded pages
  • Core Web Vitals assessment (field data, not lab)
  • Manual actions or security issues
  • Sitemap processing status and discovered pages count

Set up weekly automated reports pulling GSC API data into your Laravel admin panel. Catch indexation drops before clients notice traffic loss. For deeper technical audits, reference the technical SEO audit guide which covers server-level diagnostics specific to Nepal hosting environments.

If you're building a Laravel application in Nepal and need hands-on implementation support, these patterns scale from single-service sites to multi-tenant platforms handling thousands of indexed pages.

Implementing SEO for Laravel Sites Complete Setup

A durable SEO for Laravel sites complete setup integrates metadata, sitemaps, schema, performance, and duplicate-content controls into your development workflow — not as post-launch patches. Start with artesaos/seotools and spatie/sitemap, validate every change against Google's tools, and monitor field metrics continuously. If you need help implementing this stack on a production Laravel application, reach out to discuss your project.

Frequently Asked Questions

The artesaos/seotools package remains the standard for Laravel 12 in 2026. It handles meta tags, OpenGraph, Twitter Cards, and JSON-LD structured data directly within Blade templates or controllers without requiring heavy frontend dependencies.

Use artesaos/seotools to set metadata in your controller based on Eloquent model attributes, then render them in your master layout using the provided Blade directives. This ensures every page has unique, indexable title and description tags derived from your actual database content rather than static defaults.

No, Laravel requires the spatie/laravel-sitemap package to generate XML sitemaps. You must configure a scheduled Artisan command to regenerate the sitemap periodically, ensuring new content from your database is discoverable by search engines without manual intervention or external crawling services.

A complete technical SEO setup typically costs between NPR 25,000 and NPR 60,000 (USD 190–450) depending on site complexity. This covers schema implementation, sitemap configuration, Core Web Vitals optimization, and redirect mapping, excluding ongoing content creation or monthly link-building retainers.

Unindexed routes usually result from missing canonical tags, improper robots.txt configuration, or JavaScript-dependent rendering that crawlers cannot parse. In my experience with legal-tech portals, ensuring server-side rendered HTML with correct canonical URLs and submitting an accurate sitemap via Google Search Console resolves most indexation failures within two weeks.

Use artesaos/seotools or spatie/schema-org to generate JSON-LD programmatically in your controllers. Pass Eloquent model data into schema builders for Article, BreadcrumbList, or FAQPage types, then inject the structured data script tag into your Blade layout. This avoids hardcoding schema and keeps markup synchronized with your dynamic content as your database grows.

Duplicate content frequently stems from pagination parameters, filter query strings, or multiple URL patterns accessing identical resources. Implement canonical tags pointing to the preferred URL version, use noindex for filtered or paginated archive pages where appropriate, and configure route model binding to enforce consistent slugs. On eCommerce projects like Nepal Gift Card, this prevented category pages from competing with product pages in search results.

Focus on reducing Largest Contentful Paint by optimizing images with modern formats, deferring non-critical CSS, and minimizing JavaScript payloads. Enable Laravel's built-in asset versioning, leverage Redis for query caching to reduce Time to First Byte, and audit third-party scripts. In production deployments on Ubuntu servers with PHP-FPM 8.4, opcache tuning alone often improves TTFB by 30-50ms.

For most Laravel business sites, server-side rendering via Blade is sufficient and simpler to maintain than SSG frameworks. Reserve static generation for high-traffic marketing pages or documentation. Dynamic applications like booking systems or client portals benefit from traditional SSR with proper caching layers, avoiding the complexity of hybrid rendering while maintaining full SEO compatibility and real-time data accuracy.

Create a dedicated redirects table or middleware to map old URLs to new routes with 301 status codes. Avoid handling redirects in web.php for large-scale migrations as it degrades performance. On projects where URL structures evolved during development, I've used database-driven redirect managers that allow non-developers to update mappings without redeploying code or risking syntax errors in route files.

Index columns used in WHERE clauses for public-facing queries, particularly slug fields, category relationships, and published_at timestamps. Add composite indexes for common filter combinations. Use EXPLAIN ANALYZE to identify slow queries affecting page load times. Proper indexing reduces database response time, directly improving TTFB metrics that influence search rankings, especially on content-heavy directories or eCommerce catalogs with thousands of records.

Configure middleware to add X-Robots-Tag noindex headers for admin panels, user dashboards, and API endpoints. Block these paths in robots.txt as a secondary measure, but rely on HTTP headers since robots.txt is advisory. For client portals like Mijar Law Associates, this ensures authenticated areas never appear in search results even if accidentally linked externally or discovered through referrer leakage.

Yes, but treat AI output as draft content requiring human review before publishing. Store generated content in a separate database field with approval workflows. Always validate factual accuracy, especially for legal or medical topics where misinformation carries liability. Implement schema markup indicating AI-assisted content where appropriate. The value lies in scaling content production while maintaining editorial standards, not replacing expertise with automated text generation.

Verify opcache is cleared post-deployment to prevent stale metadata. Check file permissions on storage and cache directories. Review GitLab CI pipelines to ensure environment variables for SEO tools are correctly injected. Test staging URLs aren't accidentally indexed. On shared EC2 infrastructure running multiple sister sites, I've found deployment-related SEO regressions usually trace back to incomplete cache invalidation or misconfigured environment-specific canonical domains.

Artesaos/seotools offers comprehensive meta tag management, OpenGraph, Twitter Cards, and JSON-LD in one package with active Laravel 12 support. Spatie/laravel-seo focuses narrowly on structured data generation with cleaner APIs but requires additional packages for meta tags. Choose artesaos for all-in-one convenience on typical business sites; choose spatie/schema-org when you only need programmatic schema generation and prefer composing minimal, single-purpose packages.

Share this article

Quick Contact Options
Choose how you want to connect me: