PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / lib / Analytics / Reporter.php
mailpoet / lib / Analytics Last commit date
Analytics.php 9 months ago Reporter.php 2 months ago ReporterCampaignData.php 2 weeks ago UnsubscribeReporter.php 3 years ago index.php 3 years ago
Reporter.php
483 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Analytics;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Automation\Engine\Data\Automation;
9 use MailPoet\Automation\Engine\Data\Step;
10 use MailPoet\Automation\Engine\Storage\AutomationStorage;
11 use MailPoet\Captcha\CaptchaConstants;
12 use MailPoet\Config\ServicesChecker;
13 use MailPoet\Cron\CronTrigger;
14 use MailPoet\Entities\DynamicSegmentFilterData;
15 use MailPoet\Entities\FormEntity;
16 use MailPoet\Form\FormsRepository;
17 use MailPoet\Listing\ListingDefinition;
18 use MailPoet\Newsletter\NewslettersRepository;
19 use MailPoet\Segments\DynamicSegments\DynamicSegmentFilterRepository;
20 use MailPoet\Segments\DynamicSegments\Filters\AutomationsEvents;
21 use MailPoet\Segments\DynamicSegments\Filters\EmailAction;
22 use MailPoet\Segments\DynamicSegments\Filters\EmailActionClickAny;
23 use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
24 use MailPoet\Segments\DynamicSegments\Filters\EmailsReceived;
25 use MailPoet\Segments\DynamicSegments\Filters\MailPoetCustomFields;
26 use MailPoet\Segments\DynamicSegments\Filters\NumberOfClicks;
27 use MailPoet\Segments\DynamicSegments\Filters\SubscriberDateField;
28 use MailPoet\Segments\DynamicSegments\Filters\SubscriberScore;
29 use MailPoet\Segments\DynamicSegments\Filters\SubscriberSegment;
30 use MailPoet\Segments\DynamicSegments\Filters\SubscriberSubscribedViaForm;
31 use MailPoet\Segments\DynamicSegments\Filters\SubscriberTag;
32 use MailPoet\Segments\DynamicSegments\Filters\SubscriberTextField;
33 use MailPoet\Segments\DynamicSegments\Filters\UserRole;
34 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceAverageSpent;
35 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
36 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCountry;
37 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCustomerTextField;
38 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceFirstOrder;
39 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceMembership;
40 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders;
41 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfReviews;
42 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
43 use MailPoet\Segments\DynamicSegments\Filters\WooCommercePurchaseDate;
44 use MailPoet\Segments\DynamicSegments\Filters\WooCommercePurchasedWithAttribute;
45 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceSingleOrderValue;
46 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceSubscription;
47 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceTag;
48 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceTotalSpent;
49 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceUsedCouponCode;
50 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceUsedPaymentMethod;
51 use MailPoet\Segments\DynamicSegments\Filters\WooCommerceUsedShippingMethod;
52 use MailPoet\Segments\SegmentsRepository;
53 use MailPoet\Services\AuthorizedEmailsController;
54 use MailPoet\Settings\Pages;
55 use MailPoet\Settings\SettingsController;
56 use MailPoet\Settings\TrackingConfig;
57 use MailPoet\Subscribers\ConfirmationEmailCustomizer;
58 use MailPoet\Subscribers\NewSubscriberNotificationMailer;
59 use MailPoet\Subscribers\SubscriberListingRepository;
60 use MailPoet\Tags\TagRepository;
61 use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
62 use MailPoet\WooCommerce\Helper as WooCommerceHelper;
63 use MailPoet\WooCommerce\Subscription;
64 use MailPoet\WP\Functions as WPFunctions;
65 use MailPoet\WPCOM\DotcomHelperFunctions;
66 use MailPoetVendor\Carbon\Carbon;
67
68 class Reporter {
69 /** @var NewslettersRepository */
70 private $newslettersRepository;
71
72 /** @var SegmentsRepository */
73 private $segmentsRepository;
74
75 /** @var DynamicSegmentFilterRepository */
76 private $dynamicSegmentFilterRepository;
77
78 /** @var TagRepository */
79 private $tagRepository;
80
81 /** @var ServicesChecker */
82 private $servicesChecker;
83
84 /** @var SettingsController */
85 private $settings;
86
87 /** @var WooCommerceHelper */
88 private $woocommerceHelper;
89
90 /** @var WPFunctions */
91 private $wp;
92
93 /** @var SubscribersFeature */
94 private $subscribersFeature;
95
96 /** @var TrackingConfig */
97 private $trackingConfig;
98
99 /** @var SubscriberListingRepository */
100 private $subscriberListingRepository;
101
102 /** @var AutomationStorage */
103 private $automationStorage;
104
105 /*** @var UnsubscribeReporter */
106 private $unsubscribeReporter;
107
108 /*** @var DotcomHelperFunctions */
109 private $dotcomHelperFunctions;
110
111 /*** @var ReporterCampaignData */
112 private $reporterCampaignData;
113
114 /** @var FormsRepository */
115 private $formsRepository;
116
117 public function __construct(
118 NewslettersRepository $newslettersRepository,
119 SegmentsRepository $segmentsRepository,
120 DynamicSegmentFilterRepository $dynamicSegmentFilterRepository,
121 TagRepository $tagRepository,
122 ServicesChecker $servicesChecker,
123 SettingsController $settings,
124 WooCommerceHelper $woocommerceHelper,
125 WPFunctions $wp,
126 SubscribersFeature $subscribersFeature,
127 TrackingConfig $trackingConfig,
128 SubscriberListingRepository $subscriberListingRepository,
129 AutomationStorage $automationStorage,
130 UnsubscribeReporter $unsubscribeReporter,
131 DotcomHelperFunctions $dotcomHelperFunctions,
132 ReporterCampaignData $reporterCampaignData,
133 FormsRepository $formsRepository
134 ) {
135 $this->newslettersRepository = $newslettersRepository;
136 $this->segmentsRepository = $segmentsRepository;
137 $this->dynamicSegmentFilterRepository = $dynamicSegmentFilterRepository;
138 $this->tagRepository = $tagRepository;
139 $this->servicesChecker = $servicesChecker;
140 $this->settings = $settings;
141 $this->woocommerceHelper = $woocommerceHelper;
142 $this->wp = $wp;
143 $this->subscribersFeature = $subscribersFeature;
144 $this->trackingConfig = $trackingConfig;
145 $this->subscriberListingRepository = $subscriberListingRepository;
146 $this->automationStorage = $automationStorage;
147 $this->unsubscribeReporter = $unsubscribeReporter;
148 $this->dotcomHelperFunctions = $dotcomHelperFunctions;
149 $this->reporterCampaignData = $reporterCampaignData;
150 $this->formsRepository = $formsRepository;
151 }
152
153 public function getData() {
154 global $wpdb, $wp_version, $woocommerce; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
155 $mta = $this->settings->get('mta', []);
156 $newsletters = $this->newslettersRepository->getAnalytics();
157 $isCronTriggerMethodWP = $this->settings->get('cron_trigger.method') === CronTrigger::METHOD_WORDPRESS;
158 $bounceAddress = $this->settings->get('bounce.address');
159 $segments = $this->segmentsRepository->getCountsPerType();
160 $hasWc = $this->woocommerceHelper->isWooCommerceActive();
161 $inactiveSubscribersMonths = (int)round((int)$this->settings->get('deactivate_subscriber_after_inactive_days') / 30);
162 $inactiveSubscribersStatus = $inactiveSubscribersMonths === 0 ? 'never' : "$inactiveSubscribersMonths months";
163 $activeFormCounts = $this->formsRepository->getActiveFormsCountByType();
164
165 $result = [
166 'PHP version' => PHP_VERSION,
167 'MySQL version' => $wpdb->db_version(),
168 'WordPress version' => $wp_version, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
169 'Multisite environment' => $this->wp->isMultisite() ? 'yes' : 'no',
170 'RTL' => $this->wp->isRtl() ? 'yes' : 'no',
171 'WP_MEMORY_LIMIT' => WP_MEMORY_LIMIT,
172 'WP_MAX_MEMORY_LIMIT' => WP_MAX_MEMORY_LIMIT,
173 'PHP memory_limit' => ini_get('memory_limit'),
174 'PHP max_execution_time' => ini_get('max_execution_time'),
175 'MailPoet Free version' => MAILPOET_VERSION,
176 'MailPoet Premium version' => (defined('MAILPOET_PREMIUM_VERSION')) ? MAILPOET_PREMIUM_VERSION : 'N/A',
177 'Total number of subscribers' => $this->subscribersFeature->getSubscribersCount(),
178 'Sending Method' => $mta['method'] ?? null,
179 "Send all site's emails with" => $this->settings->get('send_transactional_emails') ? 'current sending method' : 'default WordPress sending method',
180 'Date of plugin installation' => $this->settings->get('installed_at'),
181 'Subscribe in comments' => (bool)$this->settings->get('subscribe.on_comment.enabled', false),
182 'Subscribe in registration form' => (bool)$this->settings->get('subscribe.on_register.enabled', false),
183 'Manage Subscription page > MailPoet page' => (bool)Pages::isMailpoetPage(intval($this->settings->get('subscription.pages.manage'))),
184 'Unsubscribe page > MailPoet page' => (bool)Pages::isMailpoetPage(intval($this->settings->get('subscription.pages.unsubscribe'))),
185 'Sign-up confirmation' => (bool)$this->settings->get('signup_confirmation.enabled', false),
186 'Sign-up confirmation: Confirmation page > MailPoet page' => (bool)Pages::isMailpoetPage(intval($this->settings->get('subscription.pages.confirmation'))),
187 'Bounce email address' => !empty($bounceAddress),
188 'Newsletter task scheduler (cron)' => $isCronTriggerMethodWP ? 'visitors' : 'script',
189 'Open and click tracking' => $this->trackingConfig->isEmailTrackingEnabled(),
190 'Tracking level' => $this->settings->get('tracking.level', TrackingConfig::LEVEL_FULL),
191 'Logging level' => $this->settings->get('logging', 'errors'),
192 'Premium key valid' => $this->servicesChecker->isPremiumKeyValid(),
193 'New subscriber notifications' => NewSubscriberNotificationMailer::isDisabled($this->settings->get(NewSubscriberNotificationMailer::SETTINGS_KEY)),
194 'Number of active post notifications' => $newsletters['notifications_count'],
195 'Number of active welcome emails' => $newsletters['welcome_newsletters_count'],
196 'Total number of standard newsletters sent' => $newsletters['sent_newsletters_count'],
197 'Total number of block editor gutenberg newsletters' => $newsletters['total_gutenberg_newsletter_count'],
198 'Number of block editor gutenberg newsletters sent' => $newsletters['sent_gutenberg_newsletter_count'],
199 'Number of segments' => isset($segments['dynamic']) ? (int)$segments['dynamic'] : 0,
200 'Number of lists' => isset($segments['default']) ? (int)$segments['default'] : 0,
201 'Number of subscriber tags' => $this->tagRepository->countBy([]),
202 'Site is using block theme' => $this->wp->wpIsBlockTheme(),
203 'Stop sending to inactive subscribers' => $inactiveSubscribersStatus,
204 'CAPTCHA setting' => $this->settings->get(CaptchaConstants::TYPE_SETTING_NAME, '') ?: 'disabled',
205 'Is CAPTCHA on register forms enabled' => $this->settings->get(CaptchaConstants::ON_REGISTER_FORMS_SETTING_NAME, false) ? 'yes' : 'no',
206 'users_can_register' => $this->wp->getOption('users_can_register') ? 'yes' : 'no',
207 'Is WooCommerce account creation on "My account" enabled' => $this->wp->getOption('woocommerce_enable_myaccount_registration') ?? 'no',
208 'Plugin > MailPoet Premium' => $this->wp->isPluginActive('mailpoet-premium/mailpoet-premium.php'),
209 'Plugin > bounce add-on' => $this->wp->isPluginActive('mailpoet-bounce-handler/mailpoet-bounce-handler.php'),
210 'Plugin > Bloom' => $this->wp->isPluginActive('bloom-for-publishers/bloom.php'),
211 'Plugin > WP Holler' => $this->wp->isPluginActive('holler-box/holler-box.php'),
212 'Plugin > WP-SMTP' => $this->wp->isPluginActive('wp-mail-smtp/wp_mail_smtp.php'),
213 'Plugin > WooCommerce' => $hasWc,
214 'Plugin > WooCommerce Subscription' => $this->wp->isPluginActive('woocommerce-subscriptions/woocommerce-subscriptions.php'),
215 'Plugin > WooCommerce Follow Up Emails' => $this->wp->isPluginActive('woocommerce-follow-up-emails/woocommerce-follow-up-emails.php'),
216 'Plugin > WooCommerce Email Customizer' => $this->wp->isPluginActive('woocommerce-email-customizer/woocommerce-email-customizer.php'),
217 'Plugin > WooCommerce Memberships' => $this->wp->isPluginActive('woocommerce-memberships/woocommerce-memberships.php'),
218 'Plugin > WooCommerce MailChimp' => $this->wp->isPluginActive('woocommerce-mailchimp/woocommerce-mailchimp.php'),
219 'Plugin > WooCommerce Bookings' => $this->wp->isPluginActive('woocommerce-bookings/woocommerce-bookings.php'),
220 'Plugin > MailChimp for WooCommerce' => $this->wp->isPluginActive('mailchimp-for-woocommerce/mailchimp-woocommerce.php'),
221 'Plugin > The Event Calendar' => $this->wp->isPluginActive('the-events-calendar/the-events-calendar.php'),
222 'Plugin > Gravity Forms' => $this->wp->isPluginActive('gravityforms/gravityforms.php'),
223 'Plugin > Ninja Forms' => $this->wp->isPluginActive('ninja-forms/ninja-forms.php'),
224 'Plugin > WPForms' => $this->wp->isPluginActive('wpforms-lite/wpforms.php'),
225 'Plugin > Formidable Forms' => $this->wp->isPluginActive('formidable/formidable.php'),
226 'Plugin > Contact Form 7' => $this->wp->isPluginActive('contact-form-7/wp-contact-form-7.php'),
227 'Plugin > Easy Digital Downloads' => $this->wp->isPluginActive('easy-digital-downloads/easy-digital-downloads.php'),
228 'Plugin > WooCommerce Multi-Currency' => $this->wp->isPluginActive('woocommerce-multi-currency/woocommerce-multi-currency.php'),
229 'Plugin > Multi Currency for WooCommerce' => $this->wp->isPluginActive('woo-multi-currency/woo-multi-currency.php'),
230 'Web host' => $this->settings->get('mta_group') == 'website' ? $this->settings->get('web_host') : null,
231 // Dynamic segment filters tracking -- start. If you extend segments tracking, please extend mapping in analytics.js
232 'Segment > number of machine-opens' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailOpensAbsoluteCountAction::MACHINE_TYPE),
233 'Segment > number of opens' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailOpensAbsoluteCountAction::TYPE),
234 'Segment > number of orders' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceNumberOfOrders::ACTION_NUMBER_OF_ORDERS),
235 'Segment > clicked' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailAction::ACTION_CLICKED),
236 'Segment > clicked any email' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailActionClickAny::TYPE),
237 'Segment > score' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberScore::TYPE),
238 'Segment > subscribed to list' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberSegment::TYPE),
239 'Segment > opened' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailAction::ACTION_OPENED),
240 'Segment > machine-opened' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailAction::ACTION_MACHINE_OPENED),
241 'Segment > is active member of' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE_MEMBERSHIP, WooCommerceMembership::ACTION_MEMBER_OF),
242 'Segment > has an active subscription' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE_SUBSCRIPTION, WooCommerceSubscription::ACTION_HAS_ACTIVE),
243 'Segment > is in country' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceCountry::ACTION_CUSTOMER_COUNTRY),
244 'Segment > MailPoet custom field' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE),
245 'Segment > purchased in category' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceCategory::ACTION_CATEGORY),
246 'Segment > purchased product' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceProduct::ACTION_PRODUCT),
247 'Segment > purchased with tag' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceTag::ACTION),
248 'Segment > subscribed date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::SUBSCRIBED_DATE),
249 'Segment > total spent' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceTotalSpent::ACTION_TOTAL_SPENT),
250 'Segment > first order' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceFirstOrder::ACTION),
251 'Segment > WordPress user role' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, UserRole::TYPE),
252 'Segment > subscriber tags' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberTag::TYPE),
253 'Segment > number of emails received' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailsReceived::ACTION),
254 'Segment > purchase date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommercePurchaseDate::ACTION),
255 'Segment > average order value' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceAverageSpent::ACTION),
256 'Segment > single order value' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceSingleOrderValue::ACTION_SINGLE_ORDER_VALUE),
257 'Segment > last engagement date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::LAST_ENGAGEMENT_DATE),
258 'Segment > last click date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::LAST_CLICK_DATE),
259 'Segment > last purchase date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::LAST_PURCHASE_DATE),
260 'Segment > last open date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::LAST_OPEN_DATE),
261 'Segment > last page view date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::LAST_PAGE_VIEW_DATE),
262 'Segment > last sending date' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberDateField::LAST_SENDING_DATE),
263 'Segment > first name' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberTextField::FIRST_NAME),
264 'Segment > last name' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberTextField::LAST_NAME),
265 'Segment > email' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberTextField::EMAIL),
266 'Segment > city' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceCustomerTextField::CITY),
267 'Segment > postal code' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceCustomerTextField::POSTAL_CODE),
268 'Segment > purchased with attribute' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommercePurchasedWithAttribute::ACTION),
269 'Segment > used payment method' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceUsedPaymentMethod::ACTION),
270 'Segment > used shipping method' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceUsedShippingMethod::ACTION),
271 'Segment > number of reviews' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceNumberOfReviews::ACTION),
272 'Segment > used coupon code' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_WOOCOMMERCE, WooCommerceUsedCouponCode::ACTION),
273 'Segment > entered automation' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_AUTOMATIONS, AutomationsEvents::ENTERED_ACTION),
274 'Segment > exited automation' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_AUTOMATIONS, AutomationsEvents::EXITED_ACTION),
275 'Segment > was sent' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, EmailAction::ACTION_WAS_SENT),
276 'Segment > subscribed via form' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_USER_ROLE, SubscriberSubscribedViaForm::TYPE),
277 'Segment > number of clicks' => $this->isFilterTypeActive(DynamicSegmentFilterData::TYPE_EMAIL, NumberOfClicks::ACTION),
278 // Dynamic segment filters tracking -- end. If you extend segments tracking, please extend mapping in analytics.js
279 'Number of segments with multiple conditions' => $this->segmentsRepository->getSegmentCountWithMultipleFilters(),
280 'Support tier' => $this->subscribersFeature->hasPremiumSupport() ? 'premium' : 'free',
281 'Unauthorized email notice shown' => !empty($this->settings->get(AuthorizedEmailsController::AUTHORIZED_EMAIL_ADDRESSES_ERROR_SETTING)),
282 'Sign-up confirmation: Confirmation Template > using html email editor template' => (bool)$this->settings->get(ConfirmationEmailCustomizer::SETTING_ENABLE_EMAIL_CUSTOMIZER, false),
283 'Is WordPress.com' => $this->dotcomHelperFunctions->isDotcom() ? 'yes' : 'no',
284 'WordPress.com plan' => $this->dotcomHelperFunctions->getDotcomPlan(),
285 'Forms > Number of active forms' => $activeFormCounts['all'],
286 'Forms > Number of active Below pages forms' => $activeFormCounts[FormEntity::DISPLAY_TYPE_BELOW_POST],
287 'Forms > Number of active Fixed bar forms' => $activeFormCounts[FormEntity::DISPLAY_TYPE_FIXED_BAR],
288 'Forms > Number of active Pop-up forms' => $activeFormCounts[FormEntity::DISPLAY_TYPE_POPUP],
289 'Forms > Number of active Slide–in forms' => $activeFormCounts[FormEntity::DISPLAY_TYPE_SLIDE_IN],
290 'Forms > Number of active Others (widget) forms' => $activeFormCounts[FormEntity::DISPLAY_TYPE_OTHERS],
291 'Forms > Number of active forms with first name' => $activeFormCounts['with_first_name'],
292 'Forms > Number of active forms with last name' => $activeFormCounts['with_last_name'],
293 'Forms > Number of active forms with custom fields' => $activeFormCounts['with_custom_fields'],
294 'Forms > Min custom fields' => $activeFormCounts['min_custom_fields'],
295 'Forms > Max custom fields' => $activeFormCounts['max_custom_fields'],
296 'Forms > Average custom fields' => $activeFormCounts['average_custom_fields'],
297 ];
298
299 $result = array_merge(
300 $result,
301 $this->subscriberProperties(),
302 $this->automationProperties(),
303 $this->reporterCampaignData->getCampaignAnalyticsProperties(),
304 $this->unsubscribeReporter->getProperties()
305 );
306 if ($hasWc) {
307 $result['WooCommerce version'] = $woocommerce->version;
308 $result['Number of WooCommerce subscribers'] = isset($segments['woocommerce_users']) ? (int)$segments['woocommerce_users'] : 0;
309 $result['WooCommerce: opt-in on checkout is active'] = $this->settings->get(Subscription::OPTIN_ENABLED_SETTING_NAME) ?: false;
310 $result['WooCommerce: opt-in on checkout position'] = $this->settings->get(Subscription::OPTIN_POSITION_SETTING_NAME) ?: '';
311 $result['WooCommerce: set old customers as subscribed'] = $this->settings->get('mailpoet_subscribe_old_woocommerce_customers.enabled') ?: false;
312 $result['WooCommerce email customizer is active'] = $this->settings->get('woocommerce.use_mailpoet_editor') ?: false;
313
314 $result['Number of active WooCommerce first purchase emails'] = $newsletters['first_purchase_emails_count'];
315 $result['Number of active WooCommerce purchased this product emails'] = $newsletters['product_purchased_emails_count'];
316 $result['Number of active purchased in this category'] = $newsletters['product_purchased_in_category_emails_count'];
317 $result['Number of active abandoned cart'] = $newsletters['abandoned_cart_emails_count'];
318
319 $result['Installed via WooCommerce onboarding wizard'] = $this->woocommerceHelper->wasMailPoetInstalledViaWooCommerceOnboardingWizard();
320 }
321
322 return $result;
323 }
324
325 private function automationProperties(): array {
326 $automations = $this->automationStorage->getAutomations();
327 $activeAutomations = array_filter(
328 $automations,
329 function(Automation $automation): bool {
330 return $automation->getStatus() === Automation::STATUS_ACTIVE;
331 }
332 );
333 $activeAutomationCount = count($activeAutomations);
334 $draftAutomations = array_filter(
335 $automations,
336 function(Automation $automation): bool {
337 return $automation->getStatus() === Automation::STATUS_DRAFT;
338 }
339 );
340 $automationsWithCustomTrigger = array_filter(
341 $activeAutomations,
342 function(Automation $automation): bool {
343 return $automation->getTrigger('mailpoet:custom-trigger') !== null;
344 }
345 );
346 $automationsWithWordPressUserSubscribesTrigger = array_filter(
347 $activeAutomations,
348 function(Automation $automation): bool {
349 return $automation->getTrigger('mailpoet:wp-user-registered') !== null;
350 }
351 );
352 $automationsWithSomeoneSubscribesTrigger = array_filter(
353 $activeAutomations,
354 function(Automation $automation): bool {
355 return $automation->getTrigger('mailpoet:someone-subscribes') !== null;
356 }
357 );
358 $automationsWithOrderStatusChangedTrigger = array_filter(
359 $activeAutomations,
360 function(Automation $automation): bool {
361 return $automation->getTrigger('woocommerce:order-status-changed') !== null;
362 }
363 );
364 $automationsWithAbandonedCartTrigger = array_filter(
365 $activeAutomations,
366 function(Automation $automation): bool {
367 return $automation->getTrigger('woocommerce:abandoned-cart') !== null;
368 }
369 );
370
371 $totalSteps = 0;
372 $minSteps = null;
373 $maxSteps = 0;
374 foreach ($activeAutomations as $automation) {
375 $steps = array_filter(
376 $automation->getSteps(),
377 function(Step $step): bool {
378 return $step->getType() === Step::TYPE_ACTION;
379 }
380 );
381 $stepCount = count($steps);
382 $minSteps = $minSteps !== null ? min($stepCount, $minSteps) : $stepCount;
383 $maxSteps = max($maxSteps, $stepCount);
384 $totalSteps += $stepCount;
385 }
386 $averageSteps = $activeAutomationCount > 0 ? $totalSteps / $activeAutomationCount : 0;
387
388 $customTriggerHooks = array_unique(array_values(array_map(
389 function(Automation $automation): string {
390 $trigger = $automation->getTrigger('mailpoet:custom-trigger');
391 return $trigger ? (string)$trigger->getArgs()['hook'] : '';
392 },
393 $automationsWithCustomTrigger
394 )));
395 $customActionHooksPerAutomation = array_map(
396 function(Automation $automation): array {
397 $customActionSteps = array_filter(
398 $automation->getSteps(),
399 function(Step $step): bool {
400 return $step->getKey() === 'mailpoet:custom-action';
401 }
402 );
403 if (!$customActionSteps) {
404 return [];
405 }
406
407 return array_map(
408 function(Step $step): string {
409 return (string)$step->getArgs()['hook'];
410 },
411 $customActionSteps
412 );
413
414 },
415 $activeAutomations
416 );
417 $customActionHooks = array_values(array_unique(array_filter(array_merge(...$customActionHooksPerAutomation))));
418 return [
419 'Automation > Number of active automations' => $activeAutomationCount,
420 'Automation > Number of draft automations' => count($draftAutomations),
421 'Automation > Number of "WordPress user registers" active automations' => count($automationsWithWordPressUserSubscribesTrigger),
422 'Automation > Number of "Someone subscribes" active automations ' => count($automationsWithSomeoneSubscribesTrigger),
423 'Automation > Number of "Order status changed" active automations ' => count($automationsWithOrderStatusChangedTrigger),
424 'Automation > Number of "Subscriber abandons cart" active automations' => count($automationsWithAbandonedCartTrigger),
425 'Automation > Number of steps in shortest active automation' => $minSteps,
426 'Automation > Number of steps in longest active automation' => $maxSteps,
427 'Automation > Average number of steps in active automations' => $averageSteps,
428 'Automation > Custom Trigger Hooks' => $customTriggerHooks,
429 'Automation > Custom Action Hooks' => $customActionHooks,
430 ];
431 }
432
433 private function subscriberProperties(): array {
434 $definition = new ListingDefinition();
435 $groups = $this->subscriberListingRepository->getGroups($definition);
436 $properties = [];
437 foreach ($groups as $group) {
438 $properties['Subscribers > ' . $group['name']] = (int)$group['count'];
439 }
440
441 return $properties;
442 }
443
444 public function getTrackingData() {
445 global $wp_version, $woocommerce; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
446 $newsletters = $this->newslettersRepository->getAnalytics();
447 $segments = $this->segmentsRepository->getCountsPerType();
448 $mta = $this->settings->get('mta', []);
449 $installedAt = new Carbon($this->settings->get('installed_at'));
450 $theme = $this->wp->wpGetTheme();
451 $result = [
452 'WordPressVersion' => $wp_version, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
453 'pluginGutenberg' => $this->wp->isPluginActive('gutenberg/gutenberg.php'),
454 'installedAtIso' => $installedAt->format(Carbon::ISO8601),
455 'newslettersSent' => $newsletters['sent_newsletters_count'],
456 'welcomeEmails' => $newsletters['welcome_newsletters_count'],
457 'postnotificationEmails' => $newsletters['notifications_count'],
458 'woocommerceEmails' => $newsletters['automatic_emails_count'],
459 'subscribers' => $this->subscribersFeature->getSubscribersCount(),
460 'lists' => isset($segments['default']) ? (int)$segments['default'] : 0,
461 'sendingMethod' => $mta['method'] ?? null,
462 'woocommerceIsInstalled' => $this->woocommerceHelper->isWooCommerceActive(),
463 'blockTheme' => $this->wp->wpIsBlockTheme(),
464 'theme' => $theme->Name, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
465 'themeVersion' => $theme->Version, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
466 ];
467 if (defined('GUTENBERG_VERSION')) {
468 $result['gutenbergVersion'] = GUTENBERG_VERSION;
469 }
470 if ($this->woocommerceHelper->isWooCommerceActive()) {
471 $result['wooCommerceVersion'] = $woocommerce->version;
472 }
473 return $result;
474 }
475
476 private function isFilterTypeActive(string $filterType, string $action): bool {
477 if ($this->dynamicSegmentFilterRepository->findOnyByFilterTypeAndAction($filterType, $action)) {
478 return true;
479 }
480 return false;
481 }
482 }
483