-
Notifications
You must be signed in to change notification settings - Fork 15
Portal Help Centre
Where: the self-service portal β Knowledge Publish with: Knowledge β tick articles β Set who can see them Starts empty on purpose β every article begins as analysts only
Your customers can read your knowledge base in the self-service portal. Articles reach them three ways, in rising order of how hard the customer has to look:
| Where | When they see it |
|---|---|
| Dashboard β Popular articles | Straight away, without looking. The six most-read articles published to customers |
| Knowledge (the nav) | When they go looking β searchable list |
| Under the subject box | While typing a new ticket, if the subject matches β ticket deflection |
All three ask the same question of the database (see Under the hood), so none of them can surface something the others wouldn't.
Nothing appears until you publish something, and that isn't a bug. Every article starts as Analysts only, so that adding the visibility feature could never quietly expose anything you hadn't chosen to share. A brand-new portal Knowledge section is therefore an empty one.
To fill it:
- Go to Knowledge.
- Tick the articles you want customers to read (there's a Select all if you're publishing everything).
- Choose Analysts and signed-in customers and click Apply.
Your selection survives searching and tag filtering, so you can work through everything about VPN, then everything about printers, and apply once at the end.
π‘ Read a few of them as a customer would first. Articles written for analysts often assume access to systems the customer doesn't have, or contain internal hostnames. Publishing is one click; unpublishing after someone has read it is not.
Three levels, each including the ones more open than it:
| Level | Analysts | Signed-in customers | Anonymous web chat |
|---|---|---|---|
| Analysts only (default) | β | β | β |
| Analysts and signed-in customers | β | β | β |
| Anyone, including website chat | β | β | β |
The portal reads at the middle level, so it shows articles marked for customers and those marked public.
Never shown, whatever the level:
- Unpublished articles
- Deleted articles (in the recycle bin) β note that deleting an article does not unpublish it, so both are checked
- On a multi-company system, another company's articles. Customers see their own company's articles plus anything shared with all companies
When someone starts typing the subject of a new ticket, matching articles appear underneath the box.
It's deliberately quiet:
- Nothing appears unless there's a genuine match
- It waits until they've typed at least three characters, and pauses while they're still typing
- It never blocks or interrupts submitting a ticket
- Nothing about what was typed is recorded anywhere
It searches exactly the same articles the Knowledge page does, so it can't surface anything Knowledge itself wouldn't show.
Why it's worth publishing more than you think. Deflection only works on articles a customer is allowed to see. An excellent VPN guide marked analysts only deflects nothing.
The dashboard shows the six most-read articles you've published to customers, so the answer to "how do I reset my password?" is on screen before anyone goes looking β or raises a ticket about it.
- Ordered by how often each article has actually been read (
knowledge_articles.view_count), not by anything anyone assumed. The list reflects what your customers keep needing - The counter is the same one the analyst side increments β a read is a read, wherever it happened
- Clicking one opens it in the ordinary Knowledge reader; there is no second article viewer to keep in step
- It loads separately from the rest of the dashboard, so a slow knowledge base can't delay the tickets the page is really for
- Publish nothing and the section simply says so, rather than sitting empty
π‘ Because it's ordered by reads, it's self-correcting: publish twenty articles and within a few weeks the dashboard is showing the handful people genuinely land on. It's also a decent signal for what to write next β an article climbing the list is a question your desk is answering a lot.
Sarah works at Northwind, which is one of several companies on your system. She goes to raise a ticket and types "vpn keeps dropping".
As she types, two articles appear beneath the subject box:
- How to connect to the VPN β shared with all companies, marked customers
- Northwind VPN split-tunnel settings β belongs to Northwind, marked customers
She does not see:
- VPN troubleshooting runbook β marked analysts only
- Contoso VPN configuration β belongs to a different company
- Old VPN guide (superseded) β in the recycle bin
She opens the first, follows it, and closes the tab without raising a ticket. Nothing is logged about her search.
- They can't reach an article by guessing its address. Visibility is decided in the database query, not by hiding links, so an article they're not allowed to see returns the same "not available" as one that doesn't exist β it never confirms the article is real.
- They can't ask for a different visibility level. The portal always reads as "signed-in customer" β that isn't something the browser can ask to change.
-
They can't change the sort into something else. The dashboard asks for
sort=popular; anything else falls back to alphabetical. It's a fixed list of two, not a field passed to the database. - They can't see which company an article belongs to, only whether they can read it.
- The portal section is called Knowledge β matching what it's called everywhere else in FreeITSM β and the portal's own guide is simply Help, so there aren't two things with the same name.
- Article content is written in the normal knowledge editor. Formatting, links, images and tables all carry through; anything active is stripped before display, since an article is being shown in a customer's session.
- Articles are deep-linkable β
help-centre.php?id=12opens one directly, so you can paste a link into a ticket reply.
Colour key: π₯οΈ page/UI Β· π API Β· βοΈ shared logic Β· π¨ assets Β· ποΈ storage
| π¨ | File | Role |
|---|---|---|
| π₯οΈ | self-service/help-centre.php |
The Knowledge page β search, list, article view, deep links (?id=) |
| π | api/self-service/get_knowledge_articles.php |
List + search + sort=popular, scoped. Powers all three surfaces |
| π | api/self-service/get_knowledge_article.php |
One article, scoped. Bumps view_count
|
| βοΈ | includes/knowledge/portal_reader.php |
π The scope itself β portalKnowledgeScope(), portalUserTenantId(), portalArticlePreview()
|
| π₯οΈ | self-service/index.php |
The dashboard's popular articles section |
| π₯οΈ | self-service/new-ticket.php |
The deflection suggestions under the subject box |
| π | api/knowledge/knowledge_bulk_audience.php |
The bulk "who can see them" action |
| π₯οΈ |
knowledge/index.php + assets/js/knowledge.js
|
Article ticks, the bulk bar, the audience picker |
| βοΈ | includes/knowledge/audience.php |
The three levels and the SQL filter |
| βοΈ | includes/tenancy.php |
knowledgeTenantFilterForCompany() β company scoping |
| βοΈ | includes/services/knowledge.php |
saveArticle() β the bulk action loops over it |
| π¨ | assets/js/safe-html.js |
Cleans article HTML before it reaches a customer's session |
| ποΈ | knowledge_articles.audience |
internal | customer | public, defaulting to internal
|
| ποΈ | knowledge_articles.view_count |
Reads, from both the portal and the analyst side β orders the popular list |
One question, asked in one place. Every surface above calls portalKnowledgeScope(), which returns the WHERE fragment for "articles this requester may read". That used to be copy-pasted per endpoint, and duplicated scope is the dangerous kind: nothing breaks when the copies drift, one of them just quietly starts showing more than it should.
Two details worth knowing if you're reading it: the audience is hard-coded to customer inside that function rather than accepted from the request, and knowledge uses a different company rule from tickets β a blank company on an article means shared with everyone, the opposite of a blank company on a ticket.
The bulk "who can see them" action is a thin loop over KnowledgeService::saveArticle(), which updates audience only when that key is present, rejects an invalid audience outright rather than normalising it down to internal, and refuses articles belonging to a company the analyst can't reach β a hand-rolled UPDATE would have bypassed all three. Partial success is reported, never swallowed: silently skipping three articles of fifty is how someone believes a document is published when it isn't. (The tick selection survives searching and tag filtering because it lives in JavaScript, not the DOM.)
portalArticlePreview() builds the list snippets: it drops <script>/<style> blocks whole β strip_tags alone keeps a tag's contents β and inserts a separator before each tag so a heading doesn't run into the sentence after it.
- Knowledge β writing and managing articles
- Self-Service Portal β the portal itself
- Portal privacy β what customers see of their own tickets
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- Theming & Dark Mode
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
- MobileβFriendly
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π’ Ticket numbering
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- Problem Management
- Tasks
- Assets
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
- Forms
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)