Skip to content
GitHub
Get started →

Enabled / disabled pages

The widget defaults to “every page” — once you install the snippet, it runs everywhere. Sometimes that’s wrong. Checkout pages, admin dashboards, legal documents, login flows — places where a surprise voice orb would be unwelcome.

Two configuration lists:

  • Enabled pages — if set, the widget loads only on these URL patterns.
  • Disabled pages — the widget loads everywhere except these.

You can use either. If you set both, the widget loads only on pages that match enabled_pages and do not match disabled_pages.

URL patterns

Patterns are glob-style, matched against window.location.pathname:

PatternMatches
/Only the homepage
/productsExact path /products
/products/*Any path starting with /products/
/products/**Any path starting with /products/ (recursive — same as * here)
/blog/**/draftAny blog post ending in /draft
!/checkout/**Not the checkout flow (prefix ! to negate inside a list)

Patterns are case-sensitive. Query strings (?foo=bar) and hash fragments (#top) are ignored.

Common scenarios

E-commerce

{
"enabled_pages": ["/", "/collections/**", "/products/**", "/blog/**"],
"disabled_pages": ["/checkout/**", "/account/**"]
}
  • Orb appears on shopping pages
  • Orb hides on checkout (Shopify already blocks scripts there, but this is defense in depth)
  • Orb hides on the logged-in customer account area

SaaS marketing site + app

{
"enabled_pages": ["/**"],
"disabled_pages": ["/app/**", "/admin/**", "/api/**"]
}
  • Widget on marketing pages
  • Hidden in the logged-in app and admin

Blog only

{
"enabled_pages": ["/", "/blog/**"]
}

Where to configure

Dashboard → AppearancePage visibility.

Pattern changes take effect on the next page load (after the cache TTL — usually seconds).

Programmatic control

For complex rules (e.g. “only for logged-in users,” “only on A/B test variant B”), don’t install the widget site-wide. Instead, conditionally load it from code. See the framework-specific install guides:

  • ReactuseSpelo hook
  • Next.js — wrap in a feature-flag guard
  • Vue — conditional Nuxt head injection

Automatic disables

The widget self-disables in these situations, regardless of your config:

  • Inside an <iframe> — voice in iframes has platform mic restrictions that make it unreliable
  • On http:// (non-local) — voice requires HTTPS
  • On Shopify checkout (/checkouts/*) — Shopify prohibits third-party scripts there
  • When the browser is Safari in private mode and localStorage is unavailable
  • When prefers-reduced-data is set to reduce (we honor user-agent preferences)

Mobile vs. desktop

You can’t toggle the widget by viewport. If you want mobile-only or desktop-only, use your site’s CSS to hide the widget’s root:

/* Hide on mobile */
@media (max-width: 767px) {
spelo-widget {
display: none !important;
}
}

The widget’s custom element tag is <spelo-widget> — target it from your site’s CSS.

See also