---
title: "How to Fix Indexing Issues in Vue"
description: "Diagnose \"crawled - not indexed\" and other GSC statuses, then fix them with useHead, SSR data fetching, and canonical tags in Vue."
canonical_url: "https://nuxtseo.com/learn-seo/vue/launch-and-listen/indexing-issues"
last_updated: "2026-07-16"
---

<key-takeaways>

- "Crawled - currently not indexed" means Google saw your page but chose not to index it, which also keeps it out of AI Overviews since those cite from the same index
- Google processes pages in three phases: crawling, rendering, indexing. A client-rendered SPA waits in the render queue with no fixed timeline
- Verify SSR or prerendering by checking View Source for your content, not just DevTools
- Requesting indexing through URL Inspection doesn't guarantee a result; Google still evaluates the page and prioritizes fast inclusion of useful content

</key-takeaways>

Google crawled your page but hasn't indexed it. The Page Indexing report in Search Console explains why, and most causes are fixable from your component code or build setup.

## Understanding Page Indexing Status

Search Console's Page Indexing report groups around 19 status reasons into four categories: Indexed, Not indexed, Duplicate/Alternate, and Warnings. See the [full list](https://support.google.com/webmasters/answer/7440203) for every reason. This guide covers the statuses that generate the most confusion: crawled-not-indexed, discovered-not-indexed, and the excluded statuses worth ruling out first.

![Page Indexing Status Flowchart](/images/learn-seo/vue/indexing-status-flowchart.svg)

**Indexed**: your page is in Google's index. This is a prerequisite for appearing in AI Overviews, which [cite from the same index Google Search uses](https://developers.google.com/search/docs/appearance/ai-features) rather than a separate crawl.

**Discovered - currently not indexed**: Google found your page, often via your sitemap, but hasn't crawled it yet.

**Crawled - currently not indexed**: Google crawled your page and chose not to index it.

**Excluded by robots.txt**: your robots.txt file blocks Google from accessing the page. AI Overviews draw on the same crawled index as regular search, so blocking Googlebot here excludes the page from both.

**Blocked by noindex tag**: the page has a `noindex` meta tag, so Google won't index it or use it as an AI Overviews source.

**Duplicate without user-selected canonical**: Google found multiple versions of the page and none is marked as the canonical.

**Soft 404**: the page returns a `200 OK` status but reads like a "not found" page to Google. Return a real 404 for missing content instead.

## Fixing "Crawled - Currently Not Indexed"

Google doesn't publish the specific reason for any single page. Algorithmic updates, like the June 2025 and March 2026 core updates, can shift which pages clear the bar, but the causes below are the ones you can act on directly.

### Thin or Low-Quality Content

Google skips pages with little unique value. If a page isn't good enough for a normal search result, it won't be an AI Overviews source either, since [AI features require the page to be indexed and eligible to show a snippet](https://developers.google.com/search/docs/appearance/ai-features).

Fix: add substantial, original content. Write detailed product descriptions, include images and videos, and answer user questions comprehensively. Use [Schema.org](/learn-seo/vue/mastering-meta/schema-org) to describe the page's purpose to both crawlers and LLMs.

### Duplicate Content

Multiple pages with identical or near-identical content waste Google's crawl budget. See the [Duplicate Content guide](/learn-seo/vue/controlling-crawlers/duplicate-content) for a full detection and resolution workflow. Common culprits: paginated URLs without proper canonicals, URL parameters creating duplicate versions, tag/category archives showing the same posts.

Fix: implement [canonical tags](/learn-seo/vue/controlling-crawlers/canonical-urls) pointing to the primary version:

```vue
<script setup lang="ts">
import { useHead } from '@unhead/vue'

useHead({
  link: [
    { rel: 'canonical', href: 'https://yoursite.com/primary-page' }
  ]
})
</script>
```

### Too Many Similar Pages

Sites with thousands of near-identical pages, like faceted search or filter combinations, trigger the same quality filters. Google picks a representative page and excludes the rest.

Fix: noindex filtered and parameter-based URLs, or block them in robots.txt:

```vue
<script setup lang="ts">
import { useHead } from '@unhead/vue'
import { computed } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()

// Noindex pages with filter parameters
const shouldNoIndex = computed(() =>
  route.query.color || route.query.size || route.query.sort
)

useHead({
  meta: [
    { name: 'robots', content: shouldNoIndex.value ? 'noindex, follow' : 'index, follow' }
  ]
})
</script>
```

### Poor Internal Linking

Pages with few or no internal links pointing to them signal low importance to Google. Orphan pages, reachable only via [sitemap](/learn-seo/vue/controlling-crawlers/sitemaps) and not through any `<a href>` on your site, rarely get indexed.

Fix: add internal links from relevant pages, include new pages in your main navigation or sidebar, and link from high-authority pages to new content. See the [Internal Linking](/learn-seo/vue/routes-and-rendering/internal-linking) guide for architecture patterns.

```vue
<!-- Link to important pages from your main layout -->
<template>
  <nav>
    <NuxtLink to="/important-page">
      Important Page
    </NuxtLink>
  </nav>
</template>
```

### Low Site Authority (E-E-A-T)

New sites with few backlinks face stricter indexing thresholds; Google prioritizes crawling sites it already trusts.

Fix: build backlinks and brand mentions over time: guest posts, linkable assets like tools or original research, and industry directory listings all help. This is ongoing work, not a one-time fix.

## Fixing "Discovered - Currently Not Indexed"

### Site Too New

Google publishes no fixed timeline for crawling new sites. Site owners commonly report slower initial crawling for brand-new domains until Google establishes a regular crawl pattern.

Fix: submit your sitemap, request indexing for critical pages via URL Inspection, and keep publishing regularly.

### Crawl Budget Issues

Google's crawl-budget guidance targets [sites with 10,000+ pages updated daily, or 1M+ pages updated weekly](https://developers.google.com/search/docs/crawling-indexing/large-site-managing-crawl-budget), though it calls these rough estimates rather than hard thresholds. Server speed affects the budget directly: "if the site slows down or responds with server errors, the limit goes down."

Fix: speed up your server. There's no official crawl-budget millisecond threshold, but web.dev's [TTFB guidance](https://web.dev/articles/ttfb) puts "Good" at under 800ms. Enable caching, use a CDN, optimize database queries, upgrade hosting, and monitor response times in Search Console's Crawl Stats report. Block unnecessary URLs in robots.txt:

```txt
# robots.txt
User-agent: *
# Allow important pages
Allow: /

# Block low-value sections
Disallow: /admin/
Disallow: /search?
Disallow: /*?filter=
Disallow: /print-version/
```

Pages that exist only in your sitemap, with no internal links pointing to them, get the same low-priority treatment. Fix: add internal links from relevant pages and don't rely solely on sitemaps for discovery. [Internal linking signals importance](/learn-seo/vue/routes-and-rendering/internal-linking).

## Vue SPA-Specific Issues

Single page applications create their own indexing challenges, since content loads after the initial HTML renders.

![SPA Rendering Timeline](/images/learn-seo/vue/spa-rendering-timeline.svg)

### JavaScript Rendering Problems

Google processes pages in [three phases: crawling, rendering, and indexing](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics). A client-rendered page waits in a render queue until Googlebot can execute its JavaScript, and Google gives no fixed timeline for that queue beyond saying a page "may stay on this queue for a few seconds, but it can take longer than that." Google generally executes JavaScript correctly once it gets there; the risk isn't broken rendering, it's the delay between publishing and indexing.

Test: View your page source (not DevTools). Right-click → View Page Source. If your content isn't visible in the raw HTML, Google's first crawl won't see it.

```bash
# Check if content is in initial HTML
curl -s https://yoursite.com/page | grep "expected content"
```

Fix: use Server-Side Rendering (SSR) or Static Site Generation (SSG) so content ships in the initial HTML instead of waiting on the render queue. For Vue SPAs without SSR, consider [prerendering critical pages](/learn-seo/vue/spa/prerendering).

### Content Loaded After Initial Render

Vue apps often fetch data after mounting. Google's renderer doesn't reliably wait for every async operation to finish.

```vue
<!-- PROBLEM: content loads after mount -->
<script setup lang="ts">
import { onMounted, ref } from 'vue'

const products = ref([])

onMounted(() => {
  (async () => {
    // Google's crawler might not wait for this
    products.value = await fetch('/api/products').then(r => r.json())
  })()
})
</script>

<template>
  <div v-for="product in products" :key="product.id">
    {{ product.name }}
  </div>
</template>
```

Fix: render content during SSR, or prerender pages at build time:

```vue
<!-- SOLUTION: fetch data before render -->
<script setup lang="ts">
const products = ref(await fetch('/api/products').then(r => r.json()))
</script>

<template>
  <div v-for="product in products" :key="product.id">
    {{ product.name }}
  </div>
</template>
```

For client-only apps, show loading states with descriptive text that Google can still index:

```vue
<template>
  <div>
    <h1>Product Catalog</h1>
    <p v-if="loading">
      Loading 500+ products from our catalog...
    </p>
    <div v-for="product in products" v-else :key="product.id">
      {{ product.name }}
    </div>
  </div>
</template>
```

### Client-Side Routing Issues

Vue Router changes URLs without full page reloads. If routes aren't configured correctly, Google may not discover all of them.

Fix: generate a complete sitemap listing every route. Don't rely on Google following JavaScript-generated links:

```ts
// generate-sitemap.ts
import { routes } from './router'

const sitemap = routes.map(route => ({
  url: `https://yoursite.com${route.path}`,
  lastmod: new Date().toISOString()
}))

// Write to public/sitemap.xml
```

### Testing JavaScript Rendering

Use Search Console's URL Inspection tool to see exactly what Google renders:

1. Open Search Console → URL Inspection
2. Enter your page URL, click "Test Live URL"
3. Click "View Tested Page" → "Screenshot"

Compare the screenshot to your actual page. If content is missing there, it's missing for Google too.

## AI Visibility Gaps

A page can be indexed for regular search and still get skipped by AI Overviews. Likely reasons:

- No structured data: [JSON-LD](/learn-seo/vue/mastering-meta/schema-org) helps LLMs parse a page's purpose faster than plain HTML
- Content that's hard to parse: poor heading structure or a wall of undifferentiated text
- A `nosnippet` tag: this also blocks the page from AI Overviews, since [AI features use the same snippet controls as regular search results](https://developers.google.com/search/docs/appearance/ai-features)

## Requesting Re-Indexing

After fixing an issue, request re-indexing via URL Inspection:

1. Search Console → URL Inspection
2. Enter the fixed URL
3. Click "Request Indexing"

[A crawl request doesn't guarantee inclusion](https://developers.google.com/search/docs/crawling-indexing/ask-google-to-recrawl): "Requesting a crawl does not guarantee that inclusion in search results will happen instantly or even at all. Our systems prioritize the fast inclusion of high quality, useful content." Google's crawlers also revisit indexed pages on their own to [pick up changes](https://developers.google.com/search/docs/crawling-indexing/large-site-managing-crawl-budget), so save manual requests for infrequent, important changes.

For many URLs, request indexing programmatically with the [Google Indexing API](https://developers.google.com/search/apis/indexing-api/v3/quickstart), which only covers `JobPosting` and `BroadcastEvent` structured data, or [RequestIndexing](https://requestindexing.com/) for general content:

```ts
// Request indexing via API
import { google } from 'googleapis'

async function requestIndexing(url: string) {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/indexing']
  })

  const indexing = google.indexing({ version: 'v3', auth })

  await indexing.urlNotifications.publish({
    requestBody: {
      url,
      type: 'URL_UPDATED'
    }
  })
}
```

## Monitoring Progress

Track indexing status changes over time:

1. Search Console → Page Indexing
2. Check the "Not indexed" count weekly
3. Look for status changes from "Crawled - not indexed" to "Indexed"

Google re-evaluates pages on its own schedule, not on demand, so there's no fixed timeline for a status change to show up.

Checking "Not indexed" counts by hand every week doesn't scale past a few pages. [Nuxt SEO Pro](https://nuxtseo.com/pro) tracks each page's indexing status over time and tells you why a URL is stuck (crawled-not-indexed, discovered-not-indexed, blocked, redirect), so you act on diagnoses instead of re-checking a dashboard.

Using Nuxt instead of plain Vue? Nuxt handles SSR and prerendering by default, which avoids most of the SPA-specific issues above. See the [Nuxt indexing guide](/learn-seo/nuxt/launch-and-listen/indexing-issues) for framework-specific fixes.

## Checklist

<checklist id="vue-indexing-issues">

- View source confirms your content ships in the initial HTML, not only after hydration
- Data fetches happen before render (SSR or prerender), not in a bare `onMounted()` callback
- Duplicate pages have a canonical tag pointing to one primary version
- Low-value or filtered URLs are noindexed or blocked in robots.txt
- Your sitemap lists every route so Google isn't relying on JS-generated links for discovery
- New or fixed pages are submitted via URL Inspection or the Indexing API

</checklist>
