Customer Panel Data Hooks
The fifteen data filters of the customer panel: account tabs, home page panels, invoice lists, and the partner and reseller screens.
Overview
The filters over the data the customer panel carries to the screen live here: the account tabs, the home page panels, the invoice lists, and the partner and reseller screens.
Two things recur in this group. First the active account: when a sub-user looks at another account, the id you hold belongs to that account rather than to whoever signed in. Second, amounts arrive formatted: read the raw value separately if you compare.
Reference
Hiding account tabs
Runs before the tabs of a customer account appear. Closing a tab takes the work behind it out of sight too.
Hook::add('filter:client.account.tabs', 10, function (&$tabs, &$uid, &$self) {
// Visibility ONLY: it does not close the operation.
if (!$self) $tabs['security'] = false;
});Widening the data that reaches the template
Runs before every page of the customer site appears. Every key you add here becomes a template variable.
Hook::add('filter:client.predefined_data', 10, function (&$data, &$ctx) {
// It runs on EVERY page: check the route first.
if (($ctx['route'] ?? '') !== 'my-account') return;
$data['acme_banner'] = Acme::accountBanner();
});Changing the home page panels
Runs once the panels of the home page are prepared.
Hook::add('filter:client.homepage_panels', 10, function (&$panels) {
// All four keys must stay.
$panels['product_cards'] = Acme::reorderCards($panels['product_cards'] ?? []);
});Changing the maintenance decision
Runs after the maintenance decision is made and before the page is served. This is how you keep certain addresses out of maintenance.
Hook::add('filter:client.maintenance', 10,
function (&$passive_maintenance, $controller, $foundAdmin) {
// It reads BACKWARDS: true = maintenance is SKIPPED.
if ($controller === 'status') $passive_maintenance = true;
});Changing the invoice list rows
Runs before the customer invoice list reaches the screen.
Hook::add('filter:client.invoice_list_data', 10, function (&$rows, $uid) {
foreach ($rows as $i => $r) $rows[$i]['acme_note'] = Acme::noteFor($r['id'] ?? 0);
});Changing the invoice summary
Runs once the summary above the invoice list is prepared.
Hook::add('filter:client.invoice_list_summary', 10, function (&$summary, $uid) {
// If you change the numbers, update the notice text too.
$summary['outstanding']['show'] = Acme::hideOutstanding($uid) ? false : ($summary['outstanding']['show'] ?? false);
});Changing the invoice share address
Runs after the address is produced when a customer shares an invoice.
Hook::add('filter:client.invoice_share_url', 10, function (&$shareUrl, $id, $ownerId) {
// The address needs no sign-in: keep it out of your own store.
$shareUrl = Acme::shorten($shareUrl);
});Changing the invoice transaction list
Runs before the payment movements of an invoice reach the screen.
Hook::add('filter:client.invoice_transactions', 10, function (&$rows, $id, $invCid) {
// Refunds are in this list too.
foreach ($rows as $i => $r)
if ($r['refund'] ?? false) $rows[$i]['method'] = 'Acme refund';
});Changing the bulk payment list
Runs on the screen where a customer pays several invoices together.
Hook::add('filter:client.bulk_pay_rows', 10, function (&$rows, &$uid) {
// An invoice you remove becomes unpayable here.
$rows = array_values(array_filter($rows, fn ($r) => !Acme::onHold($r['id'] ?? 0)));
});Changing the commission list
Runs before a partner’s commission list reaches the screen.
Hook::add('filter:client.affiliate_commissions', 10,
function (&$commissions, $commissionsCtx) {
// Three states: do not total them all.
$commissions = array_values(array_filter($commissions,
fn ($c) => ($c['flag'] ?? '') !== 'rejected'));
});Changing the payout channel list
Runs once the payout channels a partner may pick are prepared.
Hook::add('filter:client.affiliate_gateways', 10, function (&$out, $gatewaysCtx) {
// Changing a label can break the match with older records.
$out[] = 'Acme Wallet';
});Changing the referral destination
Runs when a visitor clicks a partner link, before the redirect happens.
Hook::add('filter:client.affiliate_referral_redirect', 10,
function (&$redirect, $redirectCtx) {
// It runs on an invalid code too: check the flag first.
if (!($redirectCtx['valid'] ?? false)) return;
$redirect = Acme::landingFor((int) ($redirectCtx['owner_id'] ?? 0)) ?: $redirect;
});Changing the payout request amount
Runs while a partner requests a payout, before the amount is saved. What you write is what gets recorded.
Hook::add('filter:client.affiliate_withdraw_amount', 10,
function (&$amount, $uid, $cid, $amountCtx) {
// The currency is the PARTNER'S, not the store's.
$amount = Acme::roundToPayoutStep($amount, $cid);
});Changing the reseller statistics
Runs once the figures on the reseller board are worked out.
Hook::add('filter:client.reseller_stats', 10, function (&$stats, $statsCtx) {
$stats['acme_target'] = Acme::monthlyTarget((int) ($statsCtx['uid'] ?? 0));
});Changing the reseller tiers
Runs once the reseller tier list is prepared. The hook is used on two separate screens.
Hook::add('filter:client.reseller_tiers', 10, function (&$tiers, $tiersCtx) {
// On the programme page the account id arrives as ZERO.
if (($tiersCtx['scope'] ?? '') === 'program') return;
$tiers = Acme::highlightCurrent($tiers, (int) ($tiersCtx['uid'] ?? 0));
});Pitfalls
The value in the maintenance filter answers not "is maintenance on" but "will maintenance be skipped". A listener setting it true because the name sounds right opens the site to visitors while you meant it closed. Confirm the direction before changing it.
The account tab filter governs visibility only. Closing a tab does not close the operation behind it: somebody who knows the address can still request it directly. Use the matching gate to really block access.
Related Articles
Merci pour votre retour !
Notre équipe d'assistance est disponible 24h/24 pour tout ce que vous ne trouvez pas ci-dessus.