PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.33.1
MailPoet – Newsletters, Email Marketing, and Automation v5.33.1
5.37.0 5.36.1 5.36.0 5.35.1 5.35.0 5.34.3 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 / Statistics / Track / Clicks.php
mailpoet / lib / Statistics / Track Last commit date
Clicks.php 9 months ago Opens.php 2 years ago PageViewCookie.php 3 months ago SubscriberActivityTracker.php 2 years ago SubscriberCookie.php 3 months ago SubscriberHandler.php 1 year ago Unsubscribes.php 3 months ago WooCommercePurchases.php 2 years ago index.php 3 years ago
Clicks.php
200 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Statistics\Track;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Entities\NewsletterEntity;
9 use MailPoet\Entities\NewsletterLinkEntity;
10 use MailPoet\Entities\SendingQueueEntity;
11 use MailPoet\Entities\StatisticsClickEntity;
12 use MailPoet\Entities\SubscriberEntity;
13 use MailPoet\Entities\UserAgentEntity;
14 use MailPoet\Newsletter\Shortcodes\Categories\Link as LinkShortcodeCategory;
15 use MailPoet\Newsletter\Shortcodes\Shortcodes;
16 use MailPoet\Settings\TrackingConfig;
17 use MailPoet\Statistics\StatisticsClicksRepository;
18 use MailPoet\Statistics\UserAgentsRepository;
19 use MailPoet\Subscribers\SubscribersRepository;
20 use MailPoet\Util\Cookies;
21 use MailPoet\Util\Request;
22 use MailPoet\WP\Functions as WPFunctions;
23
24 class Clicks {
25
26 const REVENUE_TRACKING_COOKIE_NAME = 'mailpoet_revenue_tracking';
27 const REVENUE_TRACKING_COOKIE_EXPIRY = 60 * 60 * 24 * 14;
28
29 /** @var Cookies */
30 private $cookies;
31
32 /** @var SubscriberCookie */
33 private $subscriberCookie;
34
35 /** @var Shortcodes */
36 private $shortcodes;
37
38 /** @var LinkShortcodeCategory */
39 private $linkShortcodeCategory;
40
41 /** @var Opens */
42 private $opens;
43
44 /** @var StatisticsClicksRepository */
45 private $statisticsClicksRepository;
46
47 /** @var UserAgentsRepository */
48 private $userAgentsRepository;
49
50 /** @var SubscribersRepository */
51 private $subscribersRepository;
52
53 /** @var TrackingConfig */
54 private $trackingConfig;
55
56 /** @var Request */
57 private $request;
58
59 public function __construct(
60 Cookies $cookies,
61 SubscriberCookie $subscriberCookie,
62 Shortcodes $shortcodes,
63 Opens $opens,
64 StatisticsClicksRepository $statisticsClicksRepository,
65 UserAgentsRepository $userAgentsRepository,
66 LinkShortcodeCategory $linkShortcodeCategory,
67 SubscribersRepository $subscribersRepository,
68 TrackingConfig $trackingConfig,
69 Request $request
70 ) {
71 $this->cookies = $cookies;
72 $this->subscriberCookie = $subscriberCookie;
73 $this->shortcodes = $shortcodes;
74 $this->linkShortcodeCategory = $linkShortcodeCategory;
75 $this->opens = $opens;
76 $this->statisticsClicksRepository = $statisticsClicksRepository;
77 $this->userAgentsRepository = $userAgentsRepository;
78 $this->subscribersRepository = $subscribersRepository;
79 $this->trackingConfig = $trackingConfig;
80 $this->request = $request;
81 }
82
83 /**
84 * @param \stdClass|null $data
85 */
86 public function track($data) {
87 if (!$data || empty($data->link)) {
88 return $this->abort();
89 }
90 /** @var SubscriberEntity $subscriber */
91 $subscriber = $data->subscriber;
92 /** @var SendingQueueEntity $queue */
93 $queue = $data->queue;
94 /** @var NewsletterEntity $newsletter */
95 $newsletter = $data->newsletter;
96 /** @var NewsletterLinkEntity $link */
97 $link = $data->link;
98 $wpUserPreview = ($data->preview && ($subscriber->isWPUser()));
99 // log statistics only if the action did not come from
100 // a WP user previewing the newsletter
101 if (!$wpUserPreview) {
102 $userAgent = !empty($data->userAgent) ? $this->userAgentsRepository->findOrCreate($data->userAgent) : null;
103 $statisticsClicks = $this->statisticsClicksRepository->createOrUpdateClickCount(
104 $link,
105 $subscriber,
106 $newsletter,
107 $queue,
108 $userAgent
109 );
110 if (
111 $userAgent instanceof UserAgentEntity &&
112 ($userAgent->getUserAgentType() === UserAgentEntity::USER_AGENT_TYPE_HUMAN
113 || $statisticsClicks->getUserAgentType() === UserAgentEntity::USER_AGENT_TYPE_MACHINE)
114 ) {
115 $statisticsClicks->setUserAgent($userAgent);
116 $statisticsClicks->setUserAgentType($userAgent->getUserAgentType());
117 }
118 $this->statisticsClicksRepository->flush();
119 $this->sendRevenueCookie($statisticsClicks);
120
121 $subscriberId = $subscriber->getId();
122 if ($subscriberId) {
123 $this->subscriberCookie->setSubscriberId($subscriberId);
124 }
125
126 // track open event
127 $this->opens->track($data, $displayImage = false);
128 // Update engagement date
129 $this->subscribersRepository->maybeUpdateLastClickAt($subscriber);
130 }
131 $url = $this->processUrl($link->getUrl(), $newsletter, $subscriber, $queue, $wpUserPreview);
132 do_action('mailpoet_link_clicked', $link, $subscriber, $wpUserPreview);
133 $this->redirectToUrl($url);
134 }
135
136 private function sendRevenueCookie(StatisticsClickEntity $clicks) {
137 if ($this->trackingConfig->isCookieTrackingEnabled()) {
138 $this->cookies->set(
139 self::REVENUE_TRACKING_COOKIE_NAME,
140 [
141 'statistics_clicks' => $clicks->getId(),
142 'created_at' => time(),
143 ],
144 [
145 'expires' => time() + self::REVENUE_TRACKING_COOKIE_EXPIRY,
146 'path' => '/',
147 ]
148 );
149 }
150 }
151
152 public function processUrl(
153 string $url,
154 NewsletterEntity $newsletter,
155 SubscriberEntity $subscriber,
156 SendingQueueEntity $queue,
157 bool $wpUserPreview
158 ) {
159 if (preg_match('/\[link:(?P<action>.*?)\]/', $url, $shortcode)) {
160 if (empty($shortcode['action'])) $this->abort();
161 $processedUrl = $this->linkShortcodeCategory->processShortcodeAction(
162 $shortcode[0],
163 $newsletter,
164 $subscriber,
165 $queue,
166 $wpUserPreview
167 );
168 // If shortcode was not processed, return original shortcode unchanged
169 if ($processedUrl === null) {
170 return $shortcode[0];
171 }
172 $url = $processedUrl;
173 // We need to know the original method for unsubscribe actions
174 if ($this->request->isPost() && $url) {
175 $url = $url . (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . 'request_method=POST';
176 }
177 } else {
178 $this->shortcodes->setQueue($queue);
179 $this->shortcodes->setNewsletter($newsletter);
180 $this->shortcodes->setSubscriber($subscriber);
181 $this->shortcodes->setWpUserPreview($wpUserPreview);
182 $url = $this->shortcodes->replace($url);
183 }
184 return $url;
185 }
186
187 public function abort() {
188 global $wp_query;// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
189 WPFunctions::get()->statusHeader(404);
190 $wp_query->set_404();// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
191 WPFunctions::get()->getTemplatePart((string)404);
192 exit;
193 }
194
195 public function redirectToUrl($url) {
196 header('Location: ' . $url, true, 302);
197 exit;
198 }
199 }
200