Features

Other Frameworks

AltiusSEO.Core is frontend-agnostic. The .NET backend works with any frontend stack. Only the admin dashboard component requires Next.js.

How it works: Your frontend talks to the /api/seo/* endpoints exposed by your .NET backend. Any HTTP-capable frontend can consume them.

🅰️

Angular

TypeScript + RxJS

Use the raw HTTP API from Angular services. No npm package needed — call the endpoints directly.

1. Create an SEO service

// seo.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class SeoService {
  private readonly api = '/api/seo';
  private readonly siteId = 'my-site';

  constructor(private http: HttpClient) {}

  trackPageView(url: string, title: string) {
    return this.http.post(`${this.api}/track`, {
      siteId: this.siteId,
      pageUrl: url,
      pageTitle: title,
      referrer: document.referrer,
      userAgent: navigator.userAgent,
    }).subscribe();
  }

  checkRedirect(path: string) {
    return this.http.get<{ redirectUrl: string; statusCode: number }>(
      `${this.api}/redirect/match?siteId=${this.siteId}&path=${encodeURIComponent(path)}`
    );
  }
}

2. Track page views in the router

// app.component.ts
import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { SeoService } from './seo.service';
import { filter } from 'rxjs/operators';

@Component({ selector: 'app-root', template: '<router-outlet />' })
export class AppComponent implements OnInit {
  constructor(private router: Router, private seo: SeoService) {}

  ngOnInit() {
    this.router.events
      .pipe(filter(e => e instanceof NavigationEnd))
      .subscribe((e: NavigationEnd) => {
        this.seo.trackPageView(e.urlAfterRedirects, document.title);
      });
  }
}

3. Handle redirects in a route guard

// redirect.guard.ts
import { inject } from '@angular/core';
import { Router, CanActivateFn } from '@angular/router';
import { SeoService } from './seo.service';
import { map, catchError, of } from 'rxjs';

export const redirectGuard: CanActivateFn = (route, state) => {
  const seo = inject(SeoService);
  const router = inject(Router);

  return seo.checkRedirect(state.url).pipe(
    map(result => {
      if (result?.redirectUrl) {
        window.location.href = result.redirectUrl;
        return false;
      }
      return true;
    }),
    catchError(() => of(true))
  );
};

Admin dashboard for Angular apps

Embed the Next.js dashboard as a separate admin app, or use the raw admin API endpoints to build your own Angular admin UI.

⚛️

React (SPA / Vite)

No Next.js required

For React apps not using Next.js (Vite, Create React App, etc.), install the npm package and use the lower-level hooks directly.

npm install @altiusseo/next

Setup

// main.tsx
import { SEOProvider, SEOTracker } from '@altiusseo/next';

function App() {
  return (
    <SEOProvider apiUrl="https://your-api.com/api/seo" siteId="my-site">
      <Router>
        <Routes />
      </Router>
      <SEOTracker /> {/* auto-tracks route changes */}
    </SEOProvider>
  );
}

Per-page SEO

// pages/BlogPost.tsx
import { SEOHead } from '@altiusseo/next';

export function BlogPost({ post }) {
  return (
    <>
      <SEOHead
        title={post.title}
        description={post.excerpt}
        canonical={`https://mysite.com/blog/${post.slug}`}
      />
      <article>{post.content}</article>
    </>
  );
}

Note: SEOHead uses document.title and meta tags directly in SPA mode. For SSR/SSG (better for SEO), use Next.js with the full setup.

🔷

Blazor

WebAssembly + Server

Blazor apps share the same .NET backend — add AltiusSEO.Core once and consume it from both Blazor and any other frontend.

Backend setup (same as Next.js)

// Program.cs
builder.Services.AddAltiusSEO(options => {
    options.ConnectionString = builder.Configuration.GetConnectionString("Default");
    options.SiteId = "my-site";
});
app.UseAltiusSEODatabase();
app.MapAltiusSEO();
app.MapAltiusSEOAdmin();

Track page views from Blazor

// SeoTracker.razor
@inject HttpClient Http
@inject NavigationManager Nav
@implements IDisposable

@code {
    protected override void OnInitialized() {
        Nav.LocationChanged += OnNavigated;
        _ = TrackAsync(Nav.Uri);
    }

    private void OnNavigated(object? _, LocationChangedEventArgs e) => _ = TrackAsync(e.Location);

    private async Task TrackAsync(string url) {
        await Http.PostAsJsonAsync("/api/seo/track", new {
            siteId = "my-site",
            pageUrl = url,
            pageTitle = ""
        });
    }

    public void Dispose() => Nav.LocationChanged -= OnNavigated;
}

Add <SeoTracker /> to your MainLayout.razor.

🌐

ASP.NET MVC / Razor Pages

Server-rendered

For traditional server-rendered .NET apps, inject the SEO service directly and render meta tags in your Razor views.

Inject the SEO service in a controller

// Controllers/BlogController.cs
using AltiusSEO.Core.Services;

public class BlogController : Controller {
    private readonly ISeoMetaService _seo;

    public BlogController(ISeoMetaService seo) {
        _seo = seo;
    }

    public async Task<IActionResult> Post(string slug) {
        var post = await GetPostAsync(slug);
        var meta = await _seo.GetPageMetaAsync("my-site", Request.Path);

        ViewBag.Title = meta?.Title ?? post.Title;
        ViewBag.Description = meta?.Description ?? post.Excerpt;
        ViewBag.OgImage = meta?.OgImage ?? post.CoverImage;

        return View(post);
    }
}

Render in your Razor layout

@* Views/Shared/_Layout.cshtml *@
<head>
    <title>@ViewBag.Title</title>
    <meta name="description" content="@ViewBag.Description" />
    <meta property="og:title" content="@ViewBag.Title" />
    <meta property="og:description" content="@ViewBag.Description" />
    @if (ViewBag.OgImage != null) {
        <meta property="og:image" content="@ViewBag.OgImage" />
    }
</head>

The admin dashboard is still available by embedding the SEODashboard component in a Next.js app pointed at the same backend, or by building your own Razor admin views using the admin API endpoints.

🟨

Vanilla JS / Any Frontend

HTTP API only

Any frontend can consume the SEO tracking API with a simple fetch call.

// Minimal tracker — paste into any site
const SEO_API = 'https://your-api.com/api/seo';
const SITE_ID = 'my-site';

async function trackPageView() {
  await fetch(`${SEO_API}/track`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      siteId: SITE_ID,
      pageUrl: window.location.pathname,
      pageTitle: document.title,
      referrer: document.referrer,
      userAgent: navigator.userAgent,
    }),
  });
}

// Track on load and on SPA navigation
trackPageView();
window.addEventListener('popstate', trackPageView);

Compatibility Summary

FrontendTrackingRedirectsAdmin Dashboard
Next.js 14+✓ Native✓ Middleware✓ Full SEODashboard component
React (SPA)✓ SEOTracker⚡ Client-side✓ SEODashboard component
Angular✓ HTTP service✓ Route guard⚡ Build own or use Next.js admin
Blazor✓ HttpClient✓ NavManager⚡ Build own or use Next.js admin
ASP.NET MVC✓ JS snippet✓ Middleware⚡ Build own or use Next.js admin
Vanilla JS✓ fetch()⚡ Manual⚡ Build own or use Next.js admin