How to Configure the Satisfaction Survey in GLPI

How GLPI actually triggers, stores and measures the satisfaction survey: which glpi_entities column each setting comes from, why it sometimes never goes out (closed vs solved, the createinquest cron) and what we do while supporting client environments to lift the response rate.

In this article5 sections

A satisfaction survey nobody answers drives no decision at all. This guide shows how GLPI really triggers, stores and measures the satisfaction survey - which column each setting comes from, why it sometimes simply is not sent, and what we do while supporting client environments to get the response rate off the floor.

Where the survey is configured (and why it is per entity)

Contrary to what many people look for, the satisfaction survey in GLPI is not a global switch: it is configured per entity, under Administration > Entities > (select the entity) > Assistance tab. Each field on the screen writes to a column in the glpi_entities table, and the value can be inherited from the parent entity. Knowing the column behind each field is what lets you diagnose by SQL when the interface "says" everything is fine.

Field on screenColumn in glpi_entitiesWhat it does
Configurationinquest_config-2 inherit, 0 none, 1 internal (stars), 2 external (URL)
Create survey afterinquest_delaydays after closing until the survey is generated
Rateinquest_rate% of tickets drawn (100 = all)
Durationinquest_durationdays the user has to answer (0 = unlimited)
URL (external only)inquest_URLexternal survey endpoint, with placeholders
(internal)max_closedatewatermark: how far the cron has already processed

The Configuration field set to -2 (inherit) is the silent trap: a sub-entity may look active while it is actually inheriting "no survey" from the root. Recent versions brought the same mechanics to Changes, in equivalent columns with the _change suffix.

The real trigger: closing + cron, not the solution

This is the number one cause of "the survey is not sent". The survey is not born when the ticket is solved (status 5, Solved); it is born when the ticket is closed (status 6, Closed) and, even then, only when the createinquest cron task runs and draws that ticket within the inquest_rate. Two independent prerequisites:

  1. The ticket must close. If automatic closing is off and technicians only "solve", tickets stay Solved forever and no survey is generated. Automatic closing is the entity's own autoclose_delay setting.
  2. The cron must run in external mode. The createinquest task generates the surveys for closed tickets. In internal mode it only runs when someone loads a page - in low-traffic entities it may go days without running.

That was exactly the case in an environment we took over: the survey had been "enabled" for months and the database did not hold a single answer. It was not the template or the rate. createinquest was in internal mode (mode = 1) on a low-traffic GLPI, so the cron practically never fired; and, to make it worse, automatic closing was off, so almost nothing reached the Closed status. We turned on the operating-system external cron and adjusted autoclose_delay: surveys started being generated the same day. Ever since, checking these two points became a fixed item in our runbook whenever we take over a GLPI.

The external cron is one line in the system crontab, run as the PHP user:

# /etc/cron.d/glpi - GLPI external cron (PHP-FPM user)
# 1 run per minute; processes ALL tasks in external mode,
# including "createinquest" (satisfaction survey generation).
* * * * *  apache  /usr/bin/php /var/www/glpi/front/cron.php >/dev/null 2>&1

And a direct check in the database confirms the task is up and when it last ran:

-- State of the task that generates surveys (use a read-only user)
-- state: 0=disabled 1=waiting 2=running
-- mode:  1=internal (runs on page load)  2=external (runs on the OS cron)
-- frequency: interval in seconds (default 86400 = 1 day)
SELECT name, state, mode, frequency,
       lastrun,
       DATE_ADD(lastrun, INTERVAL frequency SECOND) AS next_expected
FROM glpi_crontasks
WHERE name = 'createinquest';

The notification template

Once the survey is generated, it is the notification that invites the user. Customize it under Setup > Notifications > Notification templates, in the template tied to the Ticket satisfaction event. Useful tags:

  • ##ticket.urlsatisfaction## - direct, authenticated link to the survey (the most important one).
  • ##ticket.id## and ##ticket.title## - reference so the user remembers the ticket.
  • ##satisfaction.text## / ##satisfaction.type## - survey text and type.

The common mistake here is to polish a long e-mail: the more text before the link, the lower the conversion. One line of context, the link, done.

Measuring the response rate for real

The honest average response rate for e-mail surveys sits in the 10% to 20% range; treating 30% as "bad" is unrealistic. Every answer lives in glpi_ticketsatisfactions, one row per generated survey. When it was not answered, date_answered is null - that is how you separate "sent" from "answered":

-- Response rate and average (last 90 days), read-only user
-- type: 1=internal (stars)  2=external (URL)
-- satisfaction: 0 to 5; date_answered null = not answered yet
SELECT
    COUNT(*)                                                   AS generated,
    SUM(date_answered IS NOT NULL)                            AS answered,
    ROUND(100 * SUM(date_answered IS NOT NULL) / COUNT(*), 1) AS response_rate_pct,
    ROUND(AVG(CASE WHEN date_answered IS NOT NULL
                   THEN satisfaction END), 2)                 AS avg_0to5
FROM glpi_ticketsatisfactions
WHERE date_begin >= DATE_SUB(CURDATE(), INTERVAL 90 DAY);

Note the average only considers those who answered. Averaging over every row (nulls included) pollutes the number and was another distortion we have already fixed in a client report.

Getting the response rate off the floor

Correct configuration is a prerequisite; answer volume is another battle. What works in practice:

  • Block new tickets until they answer with the Pending Survey module: the user meets the pending survey again when trying to open the next ticket. This moves the needle the most.
  • Lower the inquest_delay to generate the survey close to the closing, while the service is still fresh in memory.
  • Notify through another channel beyond e-mail, for example via WhatsApp.
  • Keep it simple: 1 score and 1 optional comment. A long survey kills conversion.

An inquest_rate gotcha: the draw happens at cron time and is not retroactive. Dropping from 100% to 30% does not "cancel" surveys already generated, and raising it again does not recover tickets that already passed - max_closedate only moves forward.

Need satisfaction that actually measures, with a reliable cron and a healthy response rate? NexTool GLPI support takes over the configuration, the cron monitoring and the monthly reports for your operation. Learn about the support and maintenance service.


Reviewed by the NexTool Solutions team.

Frequently Asked Questions

Two reasons dominate. The ticket may be only Solved (status 5) and never Closed (status 6) - the survey is only born at closing; check the entity's automatic closing (autoclose_delay). And the createinquest cron task may be in internal mode, which only runs on a page load; in low-traffic environments, switch to the operating-system external cron.

glpi_ticketsatisfactions, one row per generated survey: tickets_id, type (1 internal, 2 external), date_begin (generation), date_answered (null while unanswered), satisfaction (0 to 5) and comment. The per-entity configuration lives in glpi_entities (inquest_config, inquest_rate, inquest_delay, inquest_duration, inquest_URL).

By cron. Closing only makes the ticket eligible; the actual survey record is created by the createinquest task, honoring the inquest_delay (delay) and the inquest_rate (draw). Without a running cron, closed tickets stay eligible but get no survey.

The native survey is a CSAT from 0 to 5 (stars) with a comment; it is not NPS. For NPS or multiple questions, use external mode (inquest_config = 2) pointing inquest_URL at a survey tool, passing the ticket identifier as a parameter.

No. The draw happens when the cron processes each ticket and is not retroactive. Lowering the rate does not delete surveys already generated, and raising it does not recover earlier tickets - the max_closedate watermark only moves forward.

Under Setup > Notifications > Notification templates, edit the template of the Ticket satisfaction event. Use ##ticket.urlsatisfaction## for the survey link and ##ticket.id##/##ticket.title## as a reference. Keep it short: the less text before the link, the higher the conversion.

Need help?