Angular handler next navigation after SSR render?

Discussão em 'Angular' iniciado por OMANSAK, Novembro 21, 2025.

  1. OMANSAK

    OMANSAK Guest

    I'm working on an Angular application and setting the SEO tags (like title, description, and meta tags) in the standard way.

    When I monitor the <head> section using a MutationObserver, I see that the tags are being re-applied on the client side. This is the normal behavior for an Angular application using Server-Side Rendering (SSR): first, the SSR output is delivered, and then the Client-Side Rendering (CSR) kicks in, running functions like ngOnInit, which often re-apply or update the meta tags.

    Our SEO Team believes this re-rendering is causing problems with Google indexing .

    My initial attempt was to ensure the tags were only set during SSR. However, this causes an issue with subsequent client-side navigations (routing within the app) because the tags are not updated after the initial load.

    So, I decided on a hybrid approach: I want to programmatically prevent the client-side re-application of the SEO tags **if it's the initial page load (i.e., not a subsequent client-side navigation).

    I tried implementing this logic as follows:**

    this._router.events
    .pipe(
    filter(event => event instanceof NavigationEnd),
    filter((event: NavigationEnd) =>
    !event.urlAfterRedirects.startsWith('/assets')
    ),
    filter((event: NavigationEnd) =>
    !event.urlAfterRedirects.startsWith('/blog')
    ),
    filter((event: NavigationEnd) =>
    !event.urlAfterRedirects.match(/(robots\.txt|sitemap\.xml)/i)
    ),
    map((event: NavigationEnd) => {
    let route = this._activatedRoute.firstChild;
    let child = route;
    while (child) {
    if (child.firstChild) {
    child = child.firstChild;
    route = child;
    } else {
    child = null;
    }
    }
    return { route, event };
    }),
    switchMap(({ route, event }) => route.data.pipe(map(data => ({ data, event }))))
    )
    .subscribe(({ data, event }) => {
    if (this._transferStateService.tryGet<number>(TRANSFER_STATE_KEY.NAVIGATION_ID, 0) != event.id) {
    this._seoService.set(data?.title || DEFAULT_EMPTY, data?.description || DEFAULT_EMPTY, data?.canonical || DEFAULT_EMPTY);
    }

    if (PlatformInfo.IsPlatformServer) {
    this._transferStateService.set(TRANSFER_STATE_KEY.NAVIGATION_ID, event.id);
    }

    if (PlatformInfo.IsPlatformBrowser) {
    scrollTop();
    window?.ChatModule?.sendLocationInfo(event.url);
    }
    })


    I have an algorithm idea for conditional client-side rendering (CSR) based on navigation history, particularly focusing on the navigationId.

    The core assumption is:


    • In Server-Side Rendering (SSR), we assume the navigationId is always 1.


    • In the initial CSR load, we also assume the navigationId is 1.


    • The logic: If the current navigationId is 1, there's no need to execute the specific CSR code/component rendering. This component should only be rendered when a second navigation (or subsequent navigation) occurs on the client side, meaning navigationId is greater than 1.

    My questions are:


    1. Is this approach correct and robust? Are there alternative or better methods to achieve this conditional rendering based on initial load vs. subsequent navigation?


    2. The reason I implemented blow conditional logic is because I've observed that faulty navigations/routes (e.g., failed navigations or errors during routing path:'**') fire the NavigationEnd event. How can I prevent this specific CSR code from running on those faulty/failed router events?

    filter((event: NavigationEnd) =>
    !event.urlAfterRedirects.startsWith('/assets') //svg-icon
    ),
    filter((event: NavigationEnd) =>
    !event.urlAfterRedirects.startsWith('/blog') // virtual-domain
    ),
    filter((event: NavigationEnd) =>
    !event.urlAfterRedirects.match(/(robots\.txt|sitemap\.xml)/i) // dynamic create
    ),

    Continue reading...

Compartilhe esta Página