PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
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
← All changes | includes/admin/settings/class-charitable-settings.php +229 -14 1.8.11 → 1.8.13 View file →
@@ -101,19 +101,20 @@
101 101 'privacy' => __( 'Privacy', 'charitable' ),
102 102 'advanced' => __( 'Advanced', 'charitable' ),
103 103 );
104 104
105 - // Only show marketing tab if newsletter connect addon is not active.
106 - if ( ! class_exists( 'Charitable_Newsletter_Connect' ) ) {
107 - $tabs = charitable_add_settings_tab(
108 - $tabs,
109 - 'marketing',
110 - __( 'Marketing', 'charitable' ),
111 - array(
112 - 'index' => 5,
113 - )
114 - );
115 - }
105 + // Always show marketing tab. Sub-tabs (Newsletters, Conversion Tracking, Google Analytics)
106 + // handle the per-feature display: Newsletter Connect addon (which works with Lite) renders
107 + // its real UI under the Newsletters sub-tab when active; Conversion Tracking and Google
108 + // Analytics always render Pro CTAs in Lite.
109 + $tabs = charitable_add_settings_tab(
110 + $tabs,
111 + 'marketing',
112 + __( 'Marketing', 'charitable' ),
113 + array(
114 + 'index' => 5,
115 + )
116 + );
116 117
117 118 // Always show security tab.
118 119 // When spam blocker is active, it will handle the settings.
119 120 // When spam blocker is inactive, core security features will handle the settings.
@@ -136,8 +137,60 @@
136 137 return apply_filters( 'charitable_settings_tabs', $tabs );
137 138 }
138 139
139 140 /**
141 + * Return the array of sub tabs used on the Marketing settings page.
142 + *
143 + * Each label carries an inline "Pro" badge:
144 + * - Newsletters: the Newsletter Connect addon works on Lite, but the badge
145 + * still appears since the bulk of newsletter functionality is Pro-tier.
146 + * - Conversion Tracking / Google Analytics: Pro-only — badge always shown.
147 + *
148 + * @since 1.8.11.3
149 + *
150 + * @return string[] key => label.
151 + */
152 + public function get_sub_sections_marketing() {
153 + $pro_badge = ' <span class="charitable-pro-badge">' . esc_html__( 'PRO', 'charitable' ) . '</span>';
154 +
155 + return apply_filters(
156 + 'charitable_settings_sub_tabs_marketing',
157 + array(
158 + 'marketing__newsletters' => __( 'Newsletters', 'charitable' ) . $pro_badge,
159 + 'marketing__conversion_tracking' => __( 'Conversion Tracking', 'charitable' ) . $pro_badge,
160 + 'marketing__google_analytics' => __( 'Google Analytics', 'charitable' ) . $pro_badge,
161 + )
162 + );
163 + }
164 +
165 + /**
166 + * Redirect to the default Marketing sub-tab when no sub_tab is supplied.
167 + *
168 + * @since 1.8.11.3
169 + *
170 + * @return void
171 + */
172 + public function marketing_sub_tab_default() {
173 + // Don't redirect during form submissions.
174 + if ( ! empty( $_POST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
175 + return;
176 + }
177 +
178 + if ( ! charitable_is_settings_view( 'marketing' ) ) {
179 + return;
180 + }
181 +
182 + if ( isset( $_GET['sub_tab'] ) || isset( $_GET['group'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
183 + return;
184 + }
185 +
186 + wp_safe_redirect(
187 + admin_url( 'admin.php?page=charitable-settings&tab=marketing&sub_tab=newsletters' )
188 + );
189 + exit;
190 + }
191 +
192 + /**
140 193 * Optionally add the extensions tab.
141 194 *
142 195 * @since 1.3.0
143 196 * @version 1.8.5.1 Adjust index so it comes before the advanced tab.
@@ -221,10 +274,32 @@
221 274 }
222 275
223 276 register_setting( 'charitable_settings', 'charitable_settings', array( $this, 'sanitize_settings' ) );
224 277
278 + // Bridge the Newsletter Connect addon (which gates its filter on
279 + // charitable_is_settings_view('extensions')) so its fields contribute
280 + // when the user is on Marketing → Newsletters. We spoof $_GET['tab']
281 + // for the duration of get_fields() so the addon's gate passes; the
282 + // extensions section is what the view's form group already targets
283 + // on the Newsletters sub-tab. The Extensions top-level tab continues
284 + // to work as before — this only adds an additional render path.
285 + $charitable_bridge_newsletters = (
286 + isset( $_GET['tab'] ) && 'marketing' === $_GET['tab'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
287 + && isset( $_GET['sub_tab'] ) && 'newsletters' === $_GET['sub_tab'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
288 + && class_exists( 'Charitable_Newsletter_Connect' )
289 + );
290 +
291 + if ( $charitable_bridge_newsletters ) {
292 + $charitable_real_tab = $_GET['tab']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
293 + $_GET['tab'] = 'extensions'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
294 + }
295 +
225 296 $fields = $this->get_fields();
226 297
298 + if ( $charitable_bridge_newsletters ) {
299 + $_GET['tab'] = $charitable_real_tab; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
300 + }
301 +
227 302 if ( empty( $fields ) ) {
228 303 return;
229 304 }
230 305
@@ -891,11 +966,18 @@
891 966 'donors',
892 967 'security',
893 968 );
894 969
895 - $tab_value = isset( $_GET['tab'] ) ? esc_attr( $_GET['tab'] ) : ''; // phpcs:ignore
970 + $tab_value = isset( $_GET['tab'] ) ? esc_attr( $_GET['tab'] ) : ''; // phpcs:ignore
971 + $sub_tab_value = isset( $_GET['sub_tab'] ) ? esc_attr( $_GET['sub_tab'] ) : ''; // phpcs:ignore
896 972
897 973 if ( in_array( $tab_value, $tab_values_to_check ) ) { // phpcs:ignore
974 + // UTM medium follows the sub_tab when present (e.g. marketing-conversion-tracking)
975 + // so each upgrade button is attributable.
976 + $upgrade_medium = ( 'marketing' === $tab_value && ! empty( $sub_tab_value ) )
977 + ? 'marketing-' . str_replace( '_', '-', $sub_tab_value )
978 + : $tab_value;
979 +
898 980 ob_start();
899 981 ?>
900 982
901 983 <div class="charitable-education-page">
@@ -901,9 +983,20 @@
901 983 <div class="charitable-education-page">
902 984
903 985 <?php
904 986 if ( 'marketing' === $tab_value ) {
905 - $this->get_settings_cta_education_content_marketing_settings();
987 + // Default to the Newsletters CTA when no sub_tab is supplied
988 + // (the marketing_sub_tab_default redirect should normally prevent this,
989 + // but render safely if a redirect was skipped — e.g. during POST).
990 + $marketing_sub_tab = '' !== $sub_tab_value ? $sub_tab_value : 'newsletters';
991 +
992 + if ( 'conversion_tracking' === $marketing_sub_tab ) {
993 + $this->get_settings_cta_education_content_conversion_tracking();
994 + } elseif ( 'google_analytics' === $marketing_sub_tab ) {
995 + $this->get_settings_cta_education_content_google_analytics();
996 + } else {
997 + $this->get_settings_cta_education_content_marketing_settings();
998 + }
906 999 } elseif ( 'donors' === $tab_value ) {
907 1000 $this->get_settings_cta_education_content_donor_settings();
908 1001 } elseif ( 'security' === $tab_value && ! charitable_is_pro() ) {
909 1002 $this->get_settings_cta_education_content_advanced_security_settings();
@@ -922,9 +1015,9 @@
922 1015 </p>
923 1016 </div>
924 1017 <?php else : ?>
925 1018 <div class="charitable-education-page-button">
926 - <a href="<?php echo esc_url( charitable_utm_link( 'https://wpcharitable.com/lite-upgrade/', $tab_value, __( 'Upgrade to Charitable Pro', 'charitable' ) ) ); ?>" class="button button-primary" target="_blank"><?php esc_html_e( 'Upgrade to Charitable Pro', 'charitable' ); ?></a>
1019 + <a href="<?php echo esc_url( charitable_utm_link( 'https://wpcharitable.com/lite-upgrade/', $upgrade_medium, __( 'Upgrade to Charitable Pro', 'charitable' ) ) ); ?>" class="button button-primary" target="_blank"><?php esc_html_e( 'Upgrade to Charitable Pro', 'charitable' ); ?></a>
927 1020 </div>
928 1021 <?php endif; ?>
929 1022 </div>
930 1023 <?php
@@ -1044,8 +1137,130 @@
1044 1137 <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Automatically add donors to your email list', 'charitable' ); ?></li>
1045 1138 <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Organize donors with tags', 'charitable' ); ?></li>
1046 1139 <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Send email series to keep donors engaged', 'charitable' ); ?></li>
1047 1140 <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Enable multiple email services', 'charitable' ); ?></li>
1141 + </ul>
1142 + </div>
1143 + <?php
1144 + }
1145 +
1146 + /**
1147 + * Get the settings CTA education content for the Marketing → Conversion Tracking sub-tab.
1148 + *
1149 + * @since 1.8.11.3
1150 + *
1151 + * @return void
1152 + */
1153 + public function get_settings_cta_education_content_conversion_tracking() {
1154 + $assets_url = charitable()->get_path( 'assets', false );
1155 + ?>
1156 +
1157 + <div class="charitable-education-page-heading">
1158 + <h4><?php esc_html_e( 'Conversion Tracking', 'charitable' ); ?></h4>
1159 + <p><?php esc_html_e( 'Send Charitable donation events into Meta Pixel, TikTok Pixel, and Google Tag Manager. Native, code-free conversion tracking that ties every completed donation to the ad campaigns and audiences that drove it.', 'charitable' ); ?></p>
1160 + <p><?php esc_html_e( 'See which ads actually produce donations, optimize spend toward real revenue, and build remarketing audiences from your highest-value supporters.', 'charitable' ); ?></p>
1161 + </div>
1162 +
1163 + <div class="charitable-education-page-media">
1164 + <div class="charitable-education-page-video">
1165 + <figure>
1166 + <div class="charitable-education-page-video-embed">
1167 + <iframe src="https://www.youtube-nocookie.com/embed/sS-F6x6F-Fs?rel=0&amp;modestbranding=1&amp;iv_load_policy=3&amp;loop=1&amp;playlist=sS-F6x6F-Fs" title="<?php esc_attr_e( 'Introducing Conversion Tracking', 'charitable' ); ?>" allow="accelerometer; autoplay; clipboard-write; encrypted-media; picture-in-picture" allowfullscreen frameborder="0"></iframe>
1168 + </div>
1169 + <figcaption><a href="https://youtu.be/sS-F6x6F-Fs" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Watch: Introducing Conversion Tracking', 'charitable' ); ?></a></figcaption>
1170 + </figure>
1171 + </div>
1172 + <div class="charitable-education-page-images">
1173 + <figure>
1174 + <div class="charitable-education-page-images-image">
1175 + <img src="<?php echo esc_url( $assets_url ); ?>images/education/conversion-tracking/education-1.png" alt="<?php esc_attr_e( 'Conversion tracking settings', 'charitable' ); ?>">
1176 + <a href="<?php echo esc_url( $assets_url ); ?>images/education/conversion-tracking/education-1.png" class="hover" data-lity="" data-lity-desc="<?php esc_attr_e( 'Pixel + GTM settings', 'charitable' ); ?>"></a>
1177 + </div>
1178 + <figcaption><?php esc_html_e( 'Pixel + GTM settings', 'charitable' ); ?></figcaption>
1179 + </figure>
1180 + <figure>
1181 + <div class="charitable-education-page-images-image">
1182 + <img src="<?php echo esc_url( $assets_url ); ?>images/education/conversion-tracking/education-2.png" alt="<?php esc_attr_e( 'Per-donation tracking status', 'charitable' ); ?>">
1183 + <a href="<?php echo esc_url( $assets_url ); ?>images/education/conversion-tracking/education-2.png" class="hover" data-lity="" data-lity-desc="<?php esc_attr_e( 'Per-donation tracking status', 'charitable' ); ?>"></a>
1184 + </div>
1185 + <figcaption><?php esc_html_e( 'Per-donation tracking status', 'charitable' ); ?></figcaption>
1186 + </figure>
1187 + <figure>
1188 + <div class="charitable-education-page-images-image">
1189 + <img src="<?php echo esc_url( $assets_url ); ?>images/education/conversion-tracking/education-3.png" alt="<?php esc_attr_e( 'WP Consent API compliant', 'charitable' ); ?>">
1190 + <a href="<?php echo esc_url( $assets_url ); ?>images/education/conversion-tracking/education-3.png" class="hover" data-lity="" data-lity-desc="<?php esc_attr_e( 'WP Consent API compliant', 'charitable' ); ?>"></a>
1191 + </div>
1192 + <figcaption><?php esc_html_e( 'WP Consent API compliant', 'charitable' ); ?></figcaption>
1193 + </figure>
1194 + </div>
1195 + </div>
1196 +
1197 + <div class="charitable-education-page-caps">
1198 + <p><?php esc_html_e( 'Track conversions with…', 'charitable' ); ?></p>
1199 + <ul>
1200 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Meta Pixel (Facebook / Instagram)', 'charitable' ); ?></li>
1201 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'TikTok Pixel', 'charitable' ); ?></li>
1202 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Google Tag Manager (GTM)', 'charitable' ); ?></li>
1203 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Campaign page view tracking', 'charitable' ); ?></li>
1204 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Donation form open tracking', 'charitable' ); ?></li>
1205 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'WP Consent API (GDPR) integration', 'charitable' ); ?></li>
1206 + </ul>
1207 + </div>
1208 + <?php
1209 + }
1210 +
1211 + /**
1212 + * Get the settings CTA education content for the Marketing → Google Analytics sub-tab.
1213 + *
1214 + * @since 1.8.11.3
1215 + *
1216 + * @return void
1217 + */
1218 + public function get_settings_cta_education_content_google_analytics() {
1219 + $assets_url = charitable()->get_path( 'assets', false );
1220 + ?>
1221 +
1222 + <div class="charitable-education-page-heading">
1223 + <h4><?php esc_html_e( 'Google Analytics', 'charitable' ); ?></h4>
1224 + <p><?php esc_html_e( 'Send Charitable donation events into Google Analytics 4. Native GA4 integration fires purchase, refund, sign-up, and login events both browser-side via gtag.js and server-side via the Measurement Protocol — so every donation, including off-site gateways and webhook-confirmed completions, makes it into GA4.', 'charitable' ); ?></p>
1225 + <p><?php esc_html_e( 'See which campaigns and sources actually produce donations, stitch sessions across devices with hashed-email user_id, and stay EEA-compliant out of the box via Google Consent Mode v2 and the WP Consent API.', 'charitable' ); ?></p>
1226 + </div>
1227 +
1228 + <div class="charitable-education-page-media">
1229 + <div class="charitable-education-page-images">
1230 + <figure>
1231 + <div class="charitable-education-page-images-image">
1232 + <img src="<?php echo esc_url( $assets_url ); ?>images/education/google-analytics/education-1.png" alt="<?php esc_attr_e( 'Google Analytics settings', 'charitable' ); ?>">
1233 + <a href="<?php echo esc_url( $assets_url ); ?>images/education/google-analytics/education-1.png" class="hover" data-lity="" data-lity-desc="<?php esc_attr_e( 'GA4 settings + Test Connection', 'charitable' ); ?>"></a>
1234 + </div>
1235 + <figcaption><?php esc_html_e( 'GA4 settings + Test Connection', 'charitable' ); ?></figcaption>
1236 + </figure>
1237 + <figure>
1238 + <div class="charitable-education-page-images-image">
1239 + <img src="<?php echo esc_url( $assets_url ); ?>images/education/google-analytics/education-2.png" alt="<?php esc_attr_e( 'Per-donation GA metabox', 'charitable' ); ?>">
1240 + <a href="<?php echo esc_url( $assets_url ); ?>images/education/google-analytics/education-2.png" class="hover" data-lity="" data-lity-desc="<?php esc_attr_e( 'Per-donation tracking metabox', 'charitable' ); ?>"></a>
1241 + </div>
1242 + <figcaption><?php esc_html_e( 'Per-donation tracking metabox', 'charitable' ); ?></figcaption>
1243 + </figure>
1244 + <figure>
1245 + <div class="charitable-education-page-images-image">
1246 + <img src="<?php echo esc_url( $assets_url ); ?>images/education/google-analytics/education-3.png" alt="<?php esc_attr_e( 'Test connection success', 'charitable' ); ?>">
1247 + <a href="<?php echo esc_url( $assets_url ); ?>images/education/google-analytics/education-3.png" class="hover" data-lity="" data-lity-desc="<?php esc_attr_e( 'Validate your GA4 setup', 'charitable' ); ?>"></a>
1248 + </div>
1249 + <figcaption><?php esc_html_e( 'Validate your GA4 setup', 'charitable' ); ?></figcaption>
1250 + </figure>
1251 + </div>
1252 + </div>
1253 +
1254 + <div class="charitable-education-page-caps">
1255 + <p><?php esc_html_e( 'Track donations in GA4 with…', 'charitable' ); ?></p>
1256 + <ul>
1257 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'GA4 purchase events (browser + Measurement Protocol)', 'charitable' ); ?></li>
1258 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Server-side refund, sign_up, and login events', 'charitable' ); ?></li>
1259 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Full UTM capture (including utm_term and utm_id)', 'charitable' ); ?></li>
1260 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Hashed-email user_id for cross-device session stitching', 'charitable' ); ?></li>
1261 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( 'Google Consent Mode v2 + WP Consent API integration', 'charitable' ); ?></li>
1262 + <li><i class="fa fa-solid fa-check"></i> <?php esc_html_e( '"Test Connection" button to validate your GA4 setup', 'charitable' ); ?></li>
1048 1263 </ul>
1049 1264 </div>
1050 1265 <?php
1051 1266 }