PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.12.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.12.3
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / tracking / charitable-tracking-hooks.php

charitable-tracking-hooks.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.12.3, at includes/tracking/charitable-tracking-hooks.php

109 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Telemetry hooks that MUST be registered in every request context.
4 *
5 * Action/filter hooks for Charitable_Tracking that cannot live in
6 * includes/admin/tracking/charitable-tracking-admin-hooks.php, because that file
7 * is required by Charitable_Admin::load_dependencies(), which only runs when
8 * is_admin() is true (charitable.php, maybe_start_admin(), returns early
9 * otherwise).
10 *
11 * WHY THIS FILE EXISTS. Three things were registered admin-only and silently
12 * never fired:
13 *
14 * 1. charitable_usage_tracking_cron -> send_checkins(). A wp-cron.php request
15 * has is_admin() false, so the weekly check-in handler was never attached
16 * and the weekly telemetry send has never run.
17 *
18 * 2. cron_schedules -> add_schedules(), which DEFINES the 'weekly' schedule.
19 * Without it in cron context, WordPress cannot look up the interval to
20 * reschedule a due recurring event, so the event is unscheduled entirely.
21 * This is the compounding half: the event was booked in wp-admin, fired
22 * once in cron with no handler attached, failed to reschedule, and
23 * vanished. Measured against production telemetry 2026-08-03: 3,003 of
24 * 3,434 reporting sites had exactly one check-in, with created_at
25 * identical to updated_at.
26 *
27 * 3. charitable_after_save_donation -> insert_time_to_first_donation().
28 * Donations are processed on the FRONT END (donation hooks are required
29 * from charitable.php outside the admin gate), so this writer never fired
30 * for a real donation. Lite has carried this since 1.8.4.5, which means
31 * charitable_first_donation has only ever been stamped by donations created
32 * inside wp-admin.
33 *
34 * DELIBERATELY NARROW. This file only touches Charitable_Tracking, which is
35 * autoloaded. It does NOT pull Charitable_Admin or the admin functions files
36 * into front-end requests; doing so would trade a telemetry bug for a sitewide
37 * performance regression. Charitable_Tracking's consent gates read consent
38 * through Charitable_Tracking::get_usage_tracking_setting(), which falls back to
39 * the raw option when the admin-only helper is absent, so nothing here depends
40 * on admin code being loaded.
41 *
42 * LITE HAS NO NUDGE. Pro 1.8.17.4 adds a one-off upgrade check-in so existing
43 * sites deliver new payload fields immediately. Lite deliberately does not:
44 * usage tracking is opt-in here under WP.org guidelines, so there is no
45 * auto-enable routine to hang a nudge from, and the existing opt-in paths (setup
46 * wizard, Settings -> Advanced) already send immediately on consent.
47 *
48 * test_checkin() intentionally stays in the admin hooks file: it is a debug
49 * entry point gated on is_admin() and manage_options anyway.
50 *
51 * @package Charitable/Functions/Tracking
52 * @author David Bisset
53 * @copyright Copyright (c) 2026, WP Charitable LLC
54 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
55 * @since 1.8.12
56 */
57
58 // Exit if accessed directly.
59 if ( ! defined( 'ABSPATH' ) ) {
60 exit;
61 }
62
63 /**
64 * Define the 'weekly' cron schedule.
65 *
66 * MUST be registered outside admin. WordPress reschedules a due recurring event
67 * by looking its interval up in wp_get_schedules(); if 'weekly' is unknown in
68 * the request that runs cron, the event is dropped instead of rescheduled.
69 *
70 * @see Charitable_Tracking::add_schedules()
71 */
72 add_action( 'cron_schedules', array( Charitable_Tracking::get_instance(), 'add_schedules' ) );
73
74 /**
75 * Book the weekly check-in if it is not already scheduled.
76 *
77 * Registered on init in every context, not just admin, so that a site whose
78 * event was destroyed by the reschedule failure above re-books it on the next
79 * request rather than waiting for someone to load wp-admin. Guarded internally
80 * by wp_next_scheduled(), so this is a single in-memory option read per request.
81 *
82 * @see Charitable_Tracking::schedule_send()
83 */
84 add_action( 'init', array( Charitable_Tracking::get_instance(), 'schedule_send' ) );
85
86 /**
87 * Run the check-in when the cron event fires.
88 *
89 * send_checkins() re-checks consent internally, so registering the handler
90 * everywhere does not send anything from a site that has not opted in. That
91 * matters more in Lite than in Pro, because Lite is opt-in only.
92 *
93 * @see Charitable_Tracking::send_checkins()
94 */
95 add_action( 'charitable_usage_tracking_cron', array( Charitable_Tracking::get_instance(), 'send_checkins' ) );
96
97 /**
98 * Record the time of the first campaign and the first donation.
99 *
100 * The donation hook fires during front-end checkout, which is why these cannot
101 * be admin-only. They stamp charitable_first_campaign and
102 * charitable_first_donation, which the opt-in payload reports.
103 *
104 * @see Charitable_Tracking::insert_time_to_first_campaign()
105 * @see Charitable_Tracking::insert_time_to_first_donation()
106 */
107 add_action( 'charitable_campaign_processor_save_core', array( Charitable_Tracking::get_instance(), 'insert_time_to_first_campaign' ), 10, 4 );
108 add_action( 'charitable_after_save_donation', array( Charitable_Tracking::get_instance(), 'insert_time_to_first_donation' ), 10, 2 );
109