Keep Public Help Useful and Ticket Data Private
A SaaS help article answers a general question that anyone can read. A private ticket contains a particular customer's issue, account details, messages or files. Separate those content types in routing, data access and publication workflow so public documentation can be discovered without exposing customer cases.
The practical result should be two verifiable behaviors: an anonymous visitor can read the approved help article, and an unauthorized visitor cannot obtain private ticket data through any route. Search directives are a separate layer. They influence cooperating search engines; they do not enforce who may see confidential information.
The example routes and review cadence below are proposed choices for a hypothetical South African SaaS product. They are not evidence that a deployed service is indexed or secure.
Define the Route and Publication Boundary
Use distinct routes such as /help/articles/reset-password for public help and /support/tickets/98765 for a private case. The exact path names do not create security; the public route must query approved public content and the ticket route must authorize the requester.
A ticket can inspire a help article, but publication should create a separate reviewed public record. Remove names, identifiers, screenshots, private filenames and other case-specific details. Do not expose a private ticket merely by flipping its robots metadata to index.
Include public help in ordinary navigation and the public sitemap. Keep private ticket URLs out of public menus, article recommendations, sitemap entries and structured data. Review generated search pages and previews too: a public search index containing ticket subjects can leak information without exposing the full ticket.
Render Public Help for Anonymous Readers
Use a rendering approach that produces the approved title, body and useful links for anonymous visitors. Verify the actual response and rendered page; a route that exists but returns only a loading state may not provide the intended help experience.
Next.js supports static metadata and generateMetadata for route-specific metadata. Use the public help title, description and intended canonical URL, and avoid inheriting an accidental noindex directive from a private layout. Metadata configuration does not itself authorize access or guarantee that Google chooses to index the page. Next.js metadata API
For public help, allow crawling and omit unintended noindex directives. An explicit index, follow can describe the intended policy, but it is not an indexing command that guarantees a result. Confirm the response status, canonical, content and internal links, then inspect observed search behavior separately.
Authorize Private Content Before Rendering
Verify identity and current permission before loading private ticket records. Check organisation and record scope, not only whether someone is logged in. Apply the same checks to detail pages, message APIs, attachments, exports and support dashboards.
Protect metadata generation as well as the visible body. A private customer name in the page title, a ticket subject in a description, or a serialized record in an initial script can leak before the interface displays an access-denied message. Use a generic safe response when authorization fails.
OWASP recommends deny-by-default behavior and permission checks on every request. A client-side redirect or a hidden ticket button cannot substitute for a server-side decision. OWASP authorization guidance
Database grants and RLS provide another boundary when configured for the real caller. Supabase's service role bypasses RLS, and views can execute under a broader owner context. Check the effective role used by the page, API and worker. Supabase role and view boundaries
Define a consistent denial contract for each endpoint. Missing authentication may return 401 or a safe login redirect; an authenticated forbidden request may return 403 or a masked 404. A policy-filtered SELECT may return no rows. In every case, verify that protected content and metadata are absent. Do not promise that RLS itself always emits one HTTP status.
Use Noindex as Search Hygiene
Google reads a noindex directive when it can crawl the response containing it. A robots.txt block can prevent Google from seeing that directive, and robots.txt is not an access-control system. Google noindex guidance
For private tickets, keep authorization in place. Do not make confidential content anonymously accessible merely so a crawler can read a noindex tag. A safe denied response or login page can carry appropriate search directives without returning the private ticket.
Inspect the actual unauthenticated response, redirects and final login page. Also inspect the authorized response for the intended non-indexing policy. A noindex directive on content a crawler cannot access is supplementary hygiene; it is not evidence that the crawler observed the private page's tag.
If a previously public URL still appears in search, first ensure that confidential content is no longer exposed. Then use the relevant search removal and recrawl process for the safe response. Search-result removal is not a substitute for repairing the underlying data exposure.
Review Robots, Sitemaps and Public Links
Do not block intended public help URLs with robots.txt. Include only appropriate public canonical URLs in the sitemap. A sitemap helps discovery but does not guarantee crawling or indexing.
For private tickets, exclusion from the sitemap reduces intentional public exposure. A robots rule may manage crawler behavior, but it cannot secure the ticket, prove no crawling occurred or ensure a known URL disappears from results. Keep authentication and authorization as the enforced privacy boundary.
Search the rendered public navigation, sitemap, feeds, structured data and public APIs for ticket identifiers or subjects. A URL being hard to guess is not a permission check. Test a known ticket belonging to another organisation rather than relying on random IDs.
Protect Attachments and Cache Responses
Ticket files need their own authorization. Map each object to the server-owned ticket and organisation record, then check the requester's permission before download or link creation. Keeping files in a private bucket is only part of the design.
Supabase private Storage supports authenticated requests and signed links. A leaked valid signed URL grants bearer access; it does not require the holder to be the original ticket participant. Changes to Auth JWT signing keys do not revoke Storage signed links. Supabase private downloads
Short expiry is not a strict cache cutoff: a warmed Smart CDN response may outlive the signed token until the cache duration ends. Choose authenticated delivery when current permission checks are required, and verify the actual browser and CDN behavior. Supabase signed URL caching
Avoid public caching of personalized ticket HTML, API responses and exports. Verify cache headers and cache keys using two users and two organisations. A page protected at the origin can still leak if a shared cache returns one customer's response to another visitor.
Filled Public/Private Route Review Matrix
These entries are proposed expected behaviors, not completed live results.
| Checkpoint | Public help article | Private ticket | Evidence |
|---|---|---|---|
| Anonymous response | Approved body available without login | No ticket content or metadata | Raw response and rendered page |
| Metadata | Relevant public title and canonical; no unintended noindex | Non-indexing policy and safe denied metadata | Head tags and headers |
| Data source | Approved public article record | Authorized ticket and organisation records | Query and permission review |
| Public links | Linked from useful help navigation | Absent from public menus and feeds | Rendered link inventory |
| Sitemap | Appropriate canonical URL included | Ticket URL excluded | Sitemap readback |
| robots.txt | Intended crawl permitted | Crawler policy separate from privacy controls | Actual file and rationale |
| API | Public content only | Current identity and record permission checked | Allow and deny responses |
| Files | Deliberately public assets only | Authorized delivery with documented bearer-link limits | Download and cache tests |
| Monitoring | Observed crawl/index state tracked separately | Exposure checks and safe response inspected | Search report and access evidence |
Acceptance Tests for the Hypothetical Help System
Use a public help fixture, an organisation A ticket, an organisation B user and one private file. Record actual endpoint behavior and response content.
| Test | Expected outcome |
|---|---|
| Anonymous help article read | Useful approved article body and internal links returned |
| Public help metadata | Intended canonical and no accidental private directive |
| Anonymous ticket request | Safe denial or login response without customer details |
| Authorized organisation A participant | Intended ticket content returned with private search policy |
| Organisation B requests A ticket | No subject, messages, counts or customer metadata |
| Direct private message API request | Same permission boundary as ticket page |
| Attachment request or link minting without permission | Denied without exposing file details |
| Existing valid signed link shared to another browser | Documented bearer behavior; do not call this recipient authorization |
| Cached ticket response reused across users | No other user's personalized response returned |
The signed-link test is important because “download denied without a link” does not establish that a leaked link is safe. Treat minting authorization, authenticated downloads, existing bearer URLs and cache expiry as distinct checks.
Monitor Outcomes and Repair Exposure
For public help, use Search Console to inspect observed indexing, canonical choices and crawler-visible content. A local HTML check establishes eligibility details, not actual Google indexing or traffic.
For private tickets, use anonymous and cross-organisation access tests, response inspection and cache tests as the primary evidence. Search Console cannot substitute for these checks or inspect an authenticated customer's experience as that user.
Run the matrix after changes to routing, layouts, metadata, policies or caching. A proposed quarterly review can supplement change-triggered checks; it is not a universal compliance requirement.
If private content appears publicly, stop the exposure and investigate all affected routes and files before focusing on search removal. Repair authorization, remove sensitive public links or indexes, inspect cache behavior, then repeat the positive and negative tests. Keep the incident and the search-cleanup state separately documented.
Frequently asked questions
How does noindex differ from robots.txt blocking?
Noindex instructs search engines not to index a page but requires the page to be crawlable. Robots.txt blocks crawling but does not guarantee exclusion from search results if linked elsewhere.
Can private ticket pages be indexed if linked publicly?
A publicly known URL can appear in search even when content is protected. Enforce authorization to prevent confidential content access, keep private URLs out of public surfaces, and handle search directives on safe responses separately.
Should attachments in private tickets use signed URLs?
Use authenticated downloads when current per-user permission is required. Signed URLs can support limited bearer access, but anyone holding a valid link may use it and warmed caches can outlive token expiry.
How often should indexing be audited?
Test after changes to routing, metadata, policies or caching, with a scheduled review suited to the service. These checks provide technical evidence; they do not alone establish legal compliance.
If your business needs help implementing secure and SEO-friendly SaaS documentation and support systems, consider professional assistance. For tailored SaaS development services, get in touch via our SaaS development service.
If you need help reviewing the public and private boundaries of your product, get in touch about SaaS development.
Sources
- Next.js metadata API
- Supabase row-level security
- Google noindex guidance
- OWASP authorization guidance
- Supabase private downloads
- Supabase signed URL caching
For more on SEO for SaaS, see our SEO for SaaS guide. Learn about HTTPS and security best practices at HTTPS and Security. Understand user flows in our User Journey glossary.

