Personal Data Hooks
The nine hooks over consent, exports, data requests and identity documents.
Overview
The four moments of personal data: a customer gives consent, exports their data, asks for it to go, and submits identity documents.
Two hooks deliberately withhold content: the document on export, the identity paper on submission. Listeners get only a summary, because spreading that data to a second place works against the point.
Reference
Following a consent change
Runs when a customer gives or withdraws consent for data processing. It fires only on a real change: saving the same value again does not raise it.
Hook::add('action:user.gdpr_consent_changed', 10, function ($uid, $status, $given_at) {
// Take the proof stamp from here rather than reading it back.
Acme::recordConsent($uid, (bool) $status, $given_at);
});Following a data export
Runs when a customer exports their own data.
Hook::add('action:user.gdpr_exported', 10, function ($uid, $meta) {
// The document content is deliberately withheld.
Acme::auditExport($uid, (int) ($meta['size'] ?? 0));
});Following a data request being opened
Runs when a customer opens a deletion or anonymisation request.
remove for deletion, anonymize for anonymisation.Hook::add('action:user.gdpr_request_created', 10, function ($uid, $type) {
Acme::openComplianceCase($uid, $type);
});Following a data request being cancelled
Runs when a customer withdraws a request they opened.
Hook::add('action:user.gdpr_request_cancelled', 10, function ($uid, $request_id) {
Acme::closeComplianceCase($request_id);
});Following a data request being carried out
Runs after a data request is carried out. Deletion and anonymisation cannot be undone: by this point the data is already gone.
Hook::add('action:user.gdpr_processed', 10, function ($request_id, $user_id, $action) {
// The data is gone: clear your own copy as well.
if ($action !== 'cancelled') Acme::purgeMirror($user_id);
});Following documents being submitted
Runs when a customer submits identity documents.
Hook::add('action:user.documents_submitted', 10, function ($uid, $doc_meta) {
// No document content, only the reference.
Acme::queueReview($uid);
});Widening the document field types
Runs while the list of types offered when defining a document field is built. Add a field type of your own here.
Hook::add('filter:user.document_field_types', 10, function (&$types) {
$types['acme-iban'] = 'Acme IBAN check';
});Changing a document field definition
Runs before a document field is saved. Fill in the settings of a type you added here.
Hook::add('filter:user.document_field_input', 10, function (&$values, &$type) {
// Check whether it is your type first.
if ($type !== 'acme-iban') return;
$values['max_size'] = 512;
});Changing the document records view
Runs when an administrator looks at a customer’s documents, before the records reach the screen.
Hook::add('filter:user.document_records_view', 10, function (&$records, &$user_id) {
// Hide the identity number from eyes without clearance.
if (Acme::canSeeFullId()) return;
foreach ($records as $i => $r) $records[$i]['field_value'] = Acme::mask($r['field_value'] ?? '');
});Pitfalls
The export hook does not carry the document, and the submission hook does not carry the identity paper; both give a summary only. That is design, not omission: handing the data to listeners works against the protection. If you need the content, read it through your own permitted path.
By the time the removal or anonymisation hook runs the data is already gone. You must clear your own copy as well, or the customer's data lives on with you.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.