Skip to Content

Client support without Zendesk: tickets inside your Odoo

A public support page per team, an immediate acknowledgement, tracked deadlines and canned replies: our Helpdesk module, with no per-agent licence.

TL;DR: our Helpdesk module installs on top of the OCA community module and adds what was missing for real client support: a public support page per team, on your own domain, with no account or password, an immediate acknowledgement email, tracked deadlines with automatic follow-up, canned replies, a client portal and a satisfaction survey on close. All of it next to your contacts, projects and invoices, with no per-agent licence.

A client has just moved forty people onto a new environment. For the four weeks that follow, everybody has questions: the password that no longer works, the file that moved, the printer that went quiet. Those questions arrive by email, by text message, by phone, to three different people, and nobody knows how many are left.

That is exactly the situation that led us to build the most recent piece of our module: a public support page, specific to that team, at an address simple enough to write on a whiteboard.

The shared inbox, for how much longer?

Email as a support channel has three structural flaws. No team visibility: nobody knows what is pending or with whom. No priority: the urgent request waits behind the newsletter and the invoices. No measurement: there is no way to tell whether you answer in two hours or two days, let alone whether it is improving.

As long as the person who knows the client is around, it holds together. The moment they are on vacation, in a meeting or swamped, the request falls into a hole and the client follows up, rightly, in an increasingly sharp tone. Past a few requests a week, it starts to show.

The subscription reflex, and what it costs

The standard answer is to subscribe to a ticketing tool. The prices are public and worth reading in full, because every figure on display assumes an annual commitment.

Solution Listed price Billed per
Zendesk Suite Team US$55 per month, annual commitment Agent
Zendesk Support Team (ticketing only) US$19 per month, annual commitment Agent
Freshdesk Growth US$19 per month, annual commitment Agent
Odoo Enterprise (pour avoir Helpdesk) CA$44.20 per month, list price CA$55 ERP user

Two details are worth the detour. At Freshdesk, the free program is no longer the ten-agent plan people remember: it is two agents for six months. And on the Odoo side, the Helpdesk app simply does not exist in the Community edition: it is absent from the apps in the public repository, it lives in Enterprise. Getting it requires at least the Standard plan, and Odoo bills per user, not per support agent. Giving a ticket queue to three people in a thirty-person organisation means thirty licences. There is a free single-app formula, but the clue is in the name: as soon as support has to sit next to your sales and your accounting, everyone moves to a paid plan. We covered that trade-off in our Community versus Enterprise comparison.

Then there is the real cost, the one that appears on no pricing page: it is a second system. Your tickets on one side, your clients, projects and invoices on the other, and a synchronisation to maintain between them.

What we built on top of the OCA

The OCA, the Odoo Community Association, maintains more than 20,000 free modules with 1,600 contributors across 62 countries. Its ticketing module, helpdesk_mgmt, already does the basics: tickets, teams, stages, a client portal. We did not fork it. Our module installs on top and adds what was missing for client support in the real world.

One support page per team

Each support team can have its own public page, at an address shaped like /support/team-name, on your domain. The page picks up your site's header, menu and footer: this is not an orphan form hosted somewhere else.

The visitor has no account or password to create. They enter their email, a subject, a description, attach a screenshot if needed, and send. An acknowledgement leaves immediately with the request number, which settles the "did you get my email?" question. If the person is already signed in to the portal, their details are prefilled and they land straight on their request.

What makes the page useful is what gets configured per team, inside Odoo, without touching code:

An intro text and a confirmation message that belong to you. For the hypercare period that served as our test bed, the intro states the dates covered and invites people to check with their department lead first for simple usage questions. That filters as well as a triage form, without looking like one.

A configurable category selector. You choose the label ("Department" by default), the list of choices, and whether an answer is required. The choice becomes a tag on the ticket at creation. That is what lets you answer "where are requests coming from?" without imposing a twelve-field questionnaire on someone whose printer is broken.

Attachments. One screenshot is worth three rounds of email. The caps are 10 MB per file and 25 MB in total by default, and both are adjustable.

What we hardened, and why

A public form is a door open to the internet that creates records in your ERP and triggers emails. We treated it accordingly.

An invisible decoy field catches bots that fill anything resembling an input: the page politely says thank you and creates nothing. A cap of five submissions per ten minutes per IP address prevents both a flood of tickets and using the acknowledgement email as a mail bomb aimed at someone. The email format is validated server-side, not only in the browser.

The least obvious piece concerns attachments. Beyond executables and scripts, the blocked extension list includes .html, .svg and .xml files. The reason: those formats render in the browser, and a file opened by an agent from the ticket would execute inside their Odoo session. An anonymous submitter would then have a path to the account of the person answering them. For the same reason, the file type is determined by the server and never taken from what the sender declared.

What the ticket sees

Because the ticket lives in Odoo, the agent has the full file in front of them without switching tabs. The contact and their history. The preferred form of address and tone for that person, if you document that. The link to the mandate's knowledge matrix item, with an indicator that says whether the request is aligned with the agreed scope or drifting past it.

When a team is tied to an hour bank, the balance shows live on the ticket, with a ribbon once it drops below the threshold. Time is logged on the ticket itself and lands on the project, so it draws down the bank with no double entry. It is the natural extension of our hour bank module.

And since support often generates what comes next, a ticket converts into a meeting record in one click, with its number and title already filled in. Today's glitch becomes tomorrow's mandate without retyping anything. A dedicated button also opens the email composer with a client update template: the text is editable and nothing leaves on its own.

Deadlines, without the theatre

Each team sets two targets in hours: time to first response and time to resolution. The ticket shows a ribbon as soon as a target is missed, and a robot passes twice a day to drop a follow-up task on the assignee, once per ticket so the list does not turn into a minefield.

Two honest caveats. Those hours are calendar hours, not business hours: a ticket opened on a Friday at 5 p.m. with a four-hour target will be in breach on Saturday morning. And the robot records the breach, it does not anticipate it. If your contractual commitment is counted in business hours, factor that into the number you enter.

What runs by itself

Keyword rules tag tickets at creation, which spares you the manual sorting of obvious requests. Recurring answers are stored as macros, applied in one click from the ticket header and then adjusted, which keeps a consistent tone no matter who replies.

The email gateway has been hardened, because a ticket queue fed by a shared address fills up with ghosts fast. Automatic replies, out-of-office notices, bulk mail and delivery failure notices are dropped instead of creating a ticket nobody dares to close. For emergencies, a push notification can reach your phone as soon as a critical ticket arrives, with a threshold set per team.

Before opening a public support page, four decisions to make:

  1. Who actually receives, and who covers when that person is away
  2. The categories offered to the visitor, in user language rather than org-chart language
  3. The deadline you are willing to put in writing, evenings and weekends included
  4. What happens to out-of-scope requests, before they turn into a billing argument

Where AI fits in

A triage button can analyse a ticket and suggest a category, a stage, someone to assign it to and a draft first reply. Three things to know. It is triggered by hand, ticket by ticket, never automatically on everything that comes in. The suggestion appears in a tab and waits for a human, it never goes to the client. And if no AI provider is configured, the button settles for a quiet notice while the rest of the module keeps working.

That is a deliberate choice: client support is the worst place to let an automatic reply miss the mark.

What it will not do

No built-in call centre: the module handles written requests, not a phone queue. No public self-service knowledge base: the portal shows clients their own requests, not help articles. The deadline targets ignore business hours, as noted above. The satisfaction survey only goes out if a survey is attached to the team, otherwise closing a ticket stays silent.

For very high volume organisations, multilingual, open around the clock, the big players keep their relevance. Our module targets SMB and non-profit teams handling dozens of requests a week, not thousands a day.

The Law 25 angle

A support ticket contains personal information: a name, an email, sometimes a screenshot showing client or employee data. Since September 2023, a Quebec business communicating personal information outside Quebec must first carry out a privacy impact assessment, and the communication has to be covered by a written agreement. The Commission d'accès à l'information states it plainly.

This is not an argument against cloud tools, it is a file to build and keep current. When ticketing runs on your own instance, hosted where you decided, the file does not come up in the same terms. It is also what makes the support channel a natural piece of bringing a new client or a new employee on board.

On our side

Our own internal requests live in this module, at modest volume: an outage at a supplier, a mail delivery block, a maintenance window to plan. The public page was built for the hypercare mandate described above, with a mandatory department selector and push notifications wired to critical tickets.

The satisfaction survey is one thing we have not switched on for ourselves yet. It is written here because it is true, and because a module described without saying what we do not use yet is worth less.

The module is published under a free licence on our GitHub repository, along with the rest of our in-house modules. Its entry lives on our modules page.

If your client requests live in personal inboxes and nobody knows what is pending, write to us and we will show you a queue in action.

Sources

Hour banks: prepaid billing without the spreadsheet
Sell blocks of hours, draw them down through timesheets: the balance computes itself and the client sees it in real time