Skip to content

Customize URL Probes ​

Probes test alternate URL forms for known services or URL patterns to find cleaner canonical URLs.

When to Use ​

Probes are useful for:

  • Converting query parameters to path-based URLs
  • Testing platform-specific URL patterns
  • Finding cleaner URL forms that serve identical content

Unlike rewrites, which transform URLs before fetching, probes generate candidates that are tested against the original response.

Interface ​

Each probe has two methods:

typescript
type Probe = {
  match: (url: URL) => boolean
  getCandidates: (url: URL) => Array<string>
}

match ​

Return true if this probe should process the URL:

typescript
match: (url) => url.searchParams.has('feed')

getCandidates ​

Return candidate URLs to test, ordered by preference (cleanest first):

typescript
getCandidates: (url) => {
  const candidate = new URL(url)
  candidate.pathname = '/feed'
  candidate.searchParams.delete('feed')
  return [candidate.href]
}

How Probes Work ​

  1. Each probe's match function is checked in order
  2. The first matching probe generates candidates
  3. Candidates are tested sequentially via fetch + content comparison
  4. First candidate returning equivalent content becomes the new base URL
  5. If no candidates work, the original URL is kept

Only the first matching probe is used. Subsequent probes are skipped.

Built-in ​

WARNING

No URL probes are enabled by default. To use built-in probes, you must explicitly pass them via the probes option.

WordPress ​

Converts WordPress query parameter feeds to path-based URLs:

text
// Regular feeds
'https://example.com/?feed=rss2'  → 'https://example.com/feed'
'https://example.com/?feed=atom'  → 'https://example.com/feed/atom'

// Comment feeds
'https://example.com/?feed=comments-rss2' → 'https://example.com/comments/feed'
'https://example.com/?feed=comments-atom' → 'https://example.com/comments/feed/atom'

// Category/tag feeds
'https://example.com/category/news/?feed=rss2' → 'https://example.com/category/news/feed'

The probe also handles redundant parameters when the path already contains /feed:

text
'https://example.com/feed/?feed=rss2' → 'https://example.com/feed'

Examples ​

Using WordPress Probe ​

typescript
import { findCanonical, wordpressProbe } from 'feedcanon'

const url = await findCanonical('https://example.com/?feed=rss2', {
  probes: [wordpressProbe],
})
// Returns: 'https://example.com/feed' (if it serves same content)

Custom Probe ​

Create a probe for a custom URL pattern:

typescript
import { findCanonical } from 'feedcanon'
import type { Probe } from 'feedcanon'

const customProbe: Probe = {
  match: (url) => url.pathname.endsWith('.rss'),
  getCandidates: (url) => {
    const candidate = new URL(url)
    candidate.pathname = candidate.pathname.replace('.rss', '.xml')
    return [candidate.href]
  },
}

const url = await findCanonical('https://example.com/feed.rss', {
  probes: [customProbe],
})

Combining Probes ​

Use multiple probes together. The first matching probe is used:

typescript
import { findCanonical, wordpressProbe } from 'feedcanon'

const url = await findCanonical('https://example.com/?feed=rss2', {
  probes: [wordpressProbe, customProbe],
})

Disable Probes ​

Probes are optional and disabled by default. To explicitly disable:

typescript
import { findCanonical } from 'feedcanon'

const url = await findCanonical('https://example.com/?feed=rss2', {
  probes: [],
})