1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace TheIconic\Tracking\GoogleAnalytics; |
4
|
|
|
|
5
|
|
|
use TheIconic\Tracking\GoogleAnalytics\Parameters\SingleParameter; |
6
|
|
|
use TheIconic\Tracking\GoogleAnalytics\Parameters\CompoundParameterCollection; |
7
|
|
|
use TheIconic\Tracking\GoogleAnalytics\Network\HttpClient; |
8
|
|
|
use TheIconic\Tracking\GoogleAnalytics\Network\PrepareUrl; |
9
|
|
|
use TheIconic\Tracking\GoogleAnalytics\Exception\InvalidPayloadDataException; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Class Analytics |
13
|
|
|
* |
14
|
|
|
* The main interface for the clients, it relies heavily in magic methods exposing |
15
|
|
|
* an interface with method tags. |
16
|
|
|
* |
17
|
|
|
* General |
18
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProtocolVersion($value) |
19
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTrackingId($value) |
20
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAnonymizeIp($value) |
21
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDataSource($value) |
22
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setQueueTime($value) |
23
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCacheBuster($value) |
24
|
|
|
* |
25
|
|
|
* User |
26
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setClientId($value) |
27
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserId($value) |
28
|
|
|
* |
29
|
|
|
* Session |
30
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSessionControl($value) |
31
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIpOverride($value) |
32
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserAgentOverride($value) |
33
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGeographicalOverride($value) |
34
|
|
|
* |
35
|
|
|
* Traffic Sources |
36
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentReferrer($value) |
37
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignName($value) |
38
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignSource($value) |
39
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignMedium($value) |
40
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignKeyword($value) |
41
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignContent($value) |
42
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignId($value) |
43
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleAdwordsId($value) |
44
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleDisplayAdsId($value) |
45
|
|
|
* |
46
|
|
|
* System Info |
47
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenResolution($value) |
48
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setViewportSize($value) |
49
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentEncoding($value) |
50
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenColors($value) |
51
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserLanguage($value) |
52
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setJavaEnabled($value) |
53
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setFlashVersion($value) |
54
|
|
|
* |
55
|
|
|
* Hit |
56
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setHitType($value) |
57
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setNonInteractionHit($value) |
58
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendPageview() |
59
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendEvent() |
60
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendScreenview() |
61
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTransaction() |
62
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendItem() |
63
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendSocial() |
64
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendException() |
65
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTiming() |
66
|
|
|
* |
67
|
|
|
* Content Information |
68
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentLocationUrl($value) |
69
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentHostName($value) |
70
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentPath($value) |
71
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentTitle($value) |
72
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenName($value) |
73
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setLinkId($value) |
74
|
|
|
* |
75
|
|
|
* App Tracking |
76
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationName($value) |
77
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationId($value) |
78
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationVersion($value) |
79
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationInstallerId($value) |
80
|
|
|
* |
81
|
|
|
* Event Tracking |
82
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventCategory($value) |
83
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventAction($value) |
84
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventLabel($value) |
85
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventValue($value) |
86
|
|
|
* |
87
|
|
|
* E-commerce |
88
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemName($value) |
89
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemPrice($value) |
90
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemQuantity($value) |
91
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCode($value) |
92
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCategory($value) |
93
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCurrencyCode($value) |
94
|
|
|
* |
95
|
|
|
* Enhanced E-Commerce |
96
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTransactionId($value) |
97
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAffiliation($value) |
98
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRevenue($value) |
99
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTax($value) |
100
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setShipping($value) |
101
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCouponCode($value) |
102
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionList($value) |
103
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStep($value) |
104
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStepOption($value) |
105
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProduct(array $productData) |
106
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductAction($value) |
107
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToDetail() |
108
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToClick() |
109
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToAdd() |
110
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRemove() |
111
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckout() |
112
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckoutOption() |
113
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToPurchase() |
114
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRefund() |
115
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductImpressionListName($value, $index) |
116
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProductImpression(array $productData, $index) |
117
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics addPromotion(array $promotionData) |
118
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionAction($value) |
119
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToClick() |
120
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToView() |
121
|
|
|
* |
122
|
|
|
* Social Interactions |
123
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialNetwork($value) |
124
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialAction($value) |
125
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialActionTarget($value) |
126
|
|
|
* |
127
|
|
|
* Timing |
128
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingCategory($value) |
129
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingVariableName($value) |
130
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingTime($value) |
131
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingLabel($value) |
132
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageLoadTime($value) |
133
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDnsTime($value) |
134
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageDownloadTime($value) |
135
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRedirectResponseTime($value) |
136
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTcpConnectTime($value) |
137
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setServerResponseTime($value) |
138
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDomInteractiveTime($value) |
139
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentLoadTime($value) |
140
|
|
|
* |
141
|
|
|
* Exceptions |
142
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExceptionDescription($value) |
143
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIsExceptionFatal($value) |
144
|
|
|
* |
145
|
|
|
* Custom Dimension / Metrics |
146
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomDimension($value, $index) |
147
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomMetric($value, $index) |
148
|
|
|
* |
149
|
|
|
* Content Grouping |
150
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentGroup($value, $index) |
151
|
|
|
* |
152
|
|
|
* Content Experiments |
153
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentId($value) |
154
|
|
|
* @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentVariant($value) |
155
|
|
|
* |
156
|
|
|
* |
157
|
|
|
* @package TheIconic\Tracking\GoogleAnalytics |
158
|
|
|
*/ |
159
|
|
|
class Analytics |
160
|
|
|
{ |
161
|
|
|
/** |
162
|
|
|
* URI scheme for the GA API. |
163
|
|
|
* |
164
|
|
|
* @var string |
165
|
|
|
*/ |
166
|
|
|
private $uriScheme = 'http'; |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Indicates if the request to GA will be asynchronous (non-blocking). |
170
|
|
|
* |
171
|
|
|
* @var boolean |
172
|
|
|
*/ |
173
|
|
|
private $isAsyncRequest = false; |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Endpoint to connect to when sending data to GA. |
177
|
|
|
* |
178
|
|
|
* @var string |
179
|
|
|
*/ |
180
|
|
|
private $endpoint = '://www.google-analytics.com/collect'; |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Endpoint to connect to when validating hits. |
184
|
|
|
* @link https://developers.google.com/analytics/devguides/collection/protocol/v1/validating-hits |
185
|
|
|
* |
186
|
|
|
* @var string |
187
|
|
|
*/ |
188
|
|
|
private $debugEndpoint = '://www.google-analytics.com/debug/collect'; |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Indicates if the request is in debug mode(validating hits). |
192
|
|
|
* |
193
|
|
|
* @var boolean |
194
|
|
|
*/ |
195
|
|
|
private $isDebug = false; |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Holds the single parameters added to the hit. |
199
|
|
|
* |
200
|
|
|
* @var SingleParameter[] |
201
|
|
|
*/ |
202
|
|
|
private $singleParameters = []; |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Holds the compound parameters collections added to the hit. |
206
|
|
|
* |
207
|
|
|
* @var CompoundParameterCollection[] |
208
|
|
|
*/ |
209
|
|
|
private $compoundParametersCollections = []; |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Holds the HTTP client used to connect to GA. |
213
|
|
|
* |
214
|
|
|
* @var HttpClient |
215
|
|
|
*/ |
216
|
|
|
private $httpClient; |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Initializes to a list of all the available parameters to be sent in a hit. |
220
|
|
|
* |
221
|
|
|
* @var array |
222
|
|
|
*/ |
223
|
|
|
private $availableParameters = [ |
224
|
|
|
'ApplicationId' => 'AppTracking\\ApplicationId', |
225
|
|
|
'ApplicationInstallerId' => 'AppTracking\\ApplicationInstallerId', |
226
|
|
|
'ApplicationName' => 'AppTracking\\ApplicationName', |
227
|
|
|
'ApplicationVersion' => 'AppTracking\\ApplicationVersion', |
228
|
|
|
'ExperimentId' => 'ContentExperiments\\ExperimentId', |
229
|
|
|
'ExperimentVariant' => 'ContentExperiments\\ExperimentVariant', |
230
|
|
|
'ContentGroup' => 'ContentGrouping\\ContentGroup', |
231
|
|
|
'DocumentHostName' => 'ContentInformation\\DocumentHostName', |
232
|
|
|
'DocumentLocationUrl' => 'ContentInformation\\DocumentLocationUrl', |
233
|
|
|
'DocumentPath' => 'ContentInformation\\DocumentPath', |
234
|
|
|
'DocumentTitle' => 'ContentInformation\\DocumentTitle', |
235
|
|
|
'LinkId' => 'ContentInformation\\LinkId', |
236
|
|
|
'ScreenName' => 'ContentInformation\\ScreenName', |
237
|
|
|
'CustomDimension' => 'CustomDimensionsMetrics\\CustomDimension', |
238
|
|
|
'CustomMetric' => 'CustomDimensionsMetrics\\CustomMetric', |
239
|
|
|
'CurrencyCode' => 'Ecommerce\\CurrencyCode', |
240
|
|
|
'ItemCategory' => 'Ecommerce\\ItemCategory', |
241
|
|
|
'ItemCode' => 'Ecommerce\\ItemCode', |
242
|
|
|
'ItemName' => 'Ecommerce\\ItemName', |
243
|
|
|
'ItemPrice' => 'Ecommerce\\ItemPrice', |
244
|
|
|
'ItemQuantity' => 'Ecommerce\\ItemQuantity', |
245
|
|
|
'Affiliation' => 'EnhancedEcommerce\\Affiliation', |
246
|
|
|
'CheckoutStep' => 'EnhancedEcommerce\\CheckoutStep', |
247
|
|
|
'CheckoutStepOption' => 'EnhancedEcommerce\\CheckoutStepOption', |
248
|
|
|
'CouponCode' => 'EnhancedEcommerce\\CouponCode', |
249
|
|
|
'Product' => 'EnhancedEcommerce\\Product', |
250
|
|
|
'ProductAction' => 'EnhancedEcommerce\\ProductAction', |
251
|
|
|
'ProductActionList' => 'EnhancedEcommerce\\ProductActionList', |
252
|
|
|
'ProductCollection' => 'EnhancedEcommerce\\ProductCollection', |
253
|
|
|
'ProductImpression' => 'EnhancedEcommerce\\ProductImpression', |
254
|
|
|
'ProductImpressionCollection' => 'EnhancedEcommerce\\ProductImpressionCollection', |
255
|
|
|
'ProductImpressionListName' => 'EnhancedEcommerce\\ProductImpressionListName', |
256
|
|
|
'Promotion' => 'EnhancedEcommerce\\Promotion', |
257
|
|
|
'PromotionAction' => 'EnhancedEcommerce\\PromotionAction', |
258
|
|
|
'PromotionCollection' => 'EnhancedEcommerce\\PromotionCollection', |
259
|
|
|
'Revenue' => 'EnhancedEcommerce\\Revenue', |
260
|
|
|
'Shipping' => 'EnhancedEcommerce\\Shipping', |
261
|
|
|
'Tax' => 'EnhancedEcommerce\\Tax', |
262
|
|
|
'TransactionId' => 'EnhancedEcommerce\\TransactionId', |
263
|
|
|
'EventAction' => 'Event\\EventAction', |
264
|
|
|
'EventCategory' => 'Event\\EventCategory', |
265
|
|
|
'EventLabel' => 'Event\\EventLabel', |
266
|
|
|
'EventValue' => 'Event\\EventValue', |
267
|
|
|
'ExceptionDescription' => 'Exceptions\\ExceptionDescription', |
268
|
|
|
'IsExceptionFatal' => 'Exceptions\\IsExceptionFatal', |
269
|
|
|
'AnonymizeIp' => 'General\\AnonymizeIp', |
270
|
|
|
'CacheBuster' => 'General\\CacheBuster', |
271
|
|
|
'DataSource' => 'General\\DataSource', |
272
|
|
|
'ProtocolVersion' => 'General\\ProtocolVersion', |
273
|
|
|
'QueueTime' => 'General\\QueueTime', |
274
|
|
|
'TrackingId' => 'General\\TrackingId', |
275
|
|
|
'HitType' => 'Hit\\HitType', |
276
|
|
|
'NonInteractionHit' => 'Hit\\NonInteractionHit', |
277
|
|
|
'GeographicalOverride' => 'Session\\GeographicalOverride', |
278
|
|
|
'IpOverride' => 'Session\\IpOverride', |
279
|
|
|
'SessionControl' => 'Session\\SessionControl', |
280
|
|
|
'UserAgentOverride' => 'Session\\UserAgentOverride', |
281
|
|
|
'SocialAction' => 'SocialInteractions\\SocialAction', |
282
|
|
|
'SocialActionTarget' => 'SocialInteractions\\SocialActionTarget', |
283
|
|
|
'SocialNetwork' => 'SocialInteractions\\SocialNetwork', |
284
|
|
|
'DocumentEncoding' => 'SystemInfo\\DocumentEncoding', |
285
|
|
|
'FlashVersion' => 'SystemInfo\\FlashVersion', |
286
|
|
|
'JavaEnabled' => 'SystemInfo\\JavaEnabled', |
287
|
|
|
'ScreenColors' => 'SystemInfo\\ScreenColors', |
288
|
|
|
'ScreenResolution' => 'SystemInfo\\ScreenResolution', |
289
|
|
|
'UserLanguage' => 'SystemInfo\\UserLanguage', |
290
|
|
|
'ViewportSize' => 'SystemInfo\\ViewportSize', |
291
|
|
|
'ContentLoadTime' => 'Timing\\ContentLoadTime', |
292
|
|
|
'DnsTime' => 'Timing\\DnsTime', |
293
|
|
|
'DomInteractiveTime' => 'Timing\\DomInteractiveTime', |
294
|
|
|
'PageDownloadTime' => 'Timing\\PageDownloadTime', |
295
|
|
|
'PageLoadTime' => 'Timing\\PageLoadTime', |
296
|
|
|
'RedirectResponseTime' => 'Timing\\RedirectResponseTime', |
297
|
|
|
'ServerResponseTime' => 'Timing\\ServerResponseTime', |
298
|
|
|
'TcpConnectTime' => 'Timing\\TcpConnectTime', |
299
|
|
|
'UserTimingCategory' => 'Timing\\UserTimingCategory', |
300
|
|
|
'UserTimingLabel' => 'Timing\\UserTimingLabel', |
301
|
|
|
'UserTimingTime' => 'Timing\\UserTimingTime', |
302
|
|
|
'UserTimingVariableName' => 'Timing\\UserTimingVariableName', |
303
|
|
|
'CampaignContent' => 'TrafficSources\\CampaignContent', |
304
|
|
|
'CampaignId' => 'TrafficSources\\CampaignId', |
305
|
|
|
'CampaignKeyword' => 'TrafficSources\\CampaignKeyword', |
306
|
|
|
'CampaignMedium' => 'TrafficSources\\CampaignMedium', |
307
|
|
|
'CampaignName' => 'TrafficSources\\CampaignName', |
308
|
|
|
'CampaignSource' => 'TrafficSources\\CampaignSource', |
309
|
|
|
'DocumentReferrer' => 'TrafficSources\\DocumentReferrer', |
310
|
|
|
'GoogleAdwordsId' => 'TrafficSources\\GoogleAdwordsId', |
311
|
|
|
'GoogleDisplayAdsId' => 'TrafficSources\\GoogleDisplayAdsId', |
312
|
|
|
'ClientId' => 'User\\ClientId', |
313
|
|
|
'UserId' => 'User\\UserId', |
314
|
|
|
]; |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* When passed with an argument of TRUE, it will send the hit using HTTPS instead of plain HTTP. |
318
|
|
|
* It parses the available parameters. |
319
|
|
|
* |
320
|
|
|
* @param bool $isSsl |
321
|
|
|
* @throws \InvalidArgumentException |
322
|
|
|
*/ |
323
|
|
|
public function __construct($isSsl = false) |
324
|
|
|
{ |
325
|
|
|
if (!is_bool($isSsl)) { |
326
|
|
|
throw new \InvalidArgumentException('First constructor argument "isSSL" must be boolean'); |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
if ($isSsl) { |
330
|
|
|
$this->uriScheme .= 's'; |
331
|
|
|
$this->endpoint = str_replace('www', 'ssl', $this->endpoint); |
332
|
|
|
} |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Sets a request to be either synchronous or asynchronous (non-blocking). |
337
|
|
|
* |
338
|
|
|
* @param boolean $isAsyncRequest |
339
|
|
|
* @return $this |
340
|
|
|
*/ |
341
|
|
|
public function setAsyncRequest($isAsyncRequest) |
342
|
|
|
{ |
343
|
|
|
$this->isAsyncRequest = $isAsyncRequest; |
344
|
|
|
|
345
|
|
|
return $this; |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
/** |
349
|
|
|
* Makes the request to GA asynchronous (non-blocking). |
350
|
|
|
* |
351
|
|
|
* @deprecated Use setAsyncRequest(boolean $isAsyncRequest) instead. To be removed in next major version. |
352
|
|
|
* |
353
|
|
|
* @return $this |
354
|
|
|
*/ |
355
|
|
|
public function makeNonBlocking() |
356
|
|
|
{ |
357
|
|
|
$this->isAsyncRequest = true; |
358
|
|
|
|
359
|
|
|
return $this; |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* Sets the HttpClient. |
364
|
|
|
* |
365
|
|
|
* @param HttpClient $httpClient |
366
|
|
|
* @return $this |
367
|
|
|
*/ |
368
|
|
|
public function setHttpClient(HttpClient $httpClient) |
369
|
|
|
{ |
370
|
|
|
$this->httpClient = $httpClient; |
371
|
|
|
|
372
|
|
|
return $this; |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* Gets the HttpClient. |
377
|
|
|
* |
378
|
|
|
* @return HttpClient |
379
|
|
|
*/ |
380
|
|
|
private function getHttpClient() |
381
|
|
|
{ |
382
|
|
|
if ($this->httpClient === null) { |
383
|
|
|
// @codeCoverageIgnoreStart |
384
|
|
|
$this->setHttpClient(new HttpClient()); |
385
|
|
|
} |
386
|
|
|
// @codeCoverageIgnoreEnd |
387
|
|
|
|
388
|
|
|
return $this->httpClient; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Gets the full endpoint to GA. |
393
|
|
|
* |
394
|
|
|
* @return string |
395
|
|
|
*/ |
396
|
|
|
private function getEndpoint() |
397
|
|
|
{ |
398
|
|
|
return ($this->isDebug) ? $this->uriScheme . $this->debugEndpoint : $this->uriScheme . $this->endpoint; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* Sets debug mode to true or false. |
403
|
|
|
* |
404
|
|
|
* @param bool $value |
405
|
|
|
* @return \TheIconic\Tracking\GoogleAnalytics\Analytics |
406
|
|
|
*/ |
407
|
|
|
public function setDebug($value) |
408
|
|
|
{ |
409
|
|
|
$this->isDebug = $value; |
410
|
|
|
|
411
|
|
|
return $this; |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* Sends a hit to GA. The hit will contain in the payload all the parameters added before. |
416
|
|
|
* |
417
|
|
|
* @param $methodName |
418
|
|
|
* @return AnalyticsResponse |
419
|
|
|
* @throws Exception\InvalidPayloadDataException |
420
|
|
|
*/ |
421
|
|
|
private function sendHit($methodName) |
422
|
|
|
{ |
423
|
|
|
$hitType = strtoupper(substr($methodName, 4)); |
424
|
|
|
|
425
|
|
|
$hitConstant = $this->getParameterClassConstant( |
426
|
|
|
'TheIconic\Tracking\GoogleAnalytics\Parameters\Hit\HitType::HIT_TYPE_' . $hitType, |
427
|
|
|
'Hit type ' . $hitType . ' is not defined, check spelling' |
428
|
|
|
); |
429
|
|
|
|
430
|
|
|
$this->setHitType($hitConstant); |
431
|
|
|
|
432
|
|
|
if (!$this->hasMinimumRequiredParameters()) { |
433
|
|
|
throw new InvalidPayloadDataException(); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
return $this->getHttpClient()->post( |
437
|
|
|
$this->getUrl(), |
438
|
|
|
$this->isAsyncRequest |
439
|
|
|
); |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
/** |
443
|
|
|
* Build and returns URL used to send to Google Analytics. |
444
|
|
|
* |
445
|
|
|
* @return string |
446
|
|
|
*/ |
447
|
|
|
public function getUrl() |
448
|
|
|
{ |
449
|
|
|
$prepareUrl = new PrepareUrl; |
450
|
|
|
|
451
|
|
|
return $prepareUrl->build( |
452
|
|
|
$this->getEndpoint(), |
453
|
|
|
$this->singleParameters, |
454
|
|
|
$this->compoundParametersCollections |
455
|
|
|
); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
/** |
459
|
|
|
* Validates the minimum required parameters for every GA hit are being sent. |
460
|
|
|
* |
461
|
|
|
* @SuppressWarnings(PHPMD.LongVariable) |
462
|
|
|
* |
463
|
|
|
* @return bool |
464
|
|
|
*/ |
465
|
|
|
private function hasMinimumRequiredParameters() |
466
|
|
|
{ |
467
|
|
|
$minimumRequiredParameters = [ |
468
|
|
|
'v' => false, |
469
|
|
|
'tid' => false, |
470
|
|
|
'cid' => false, |
471
|
|
|
't' => false, |
472
|
|
|
]; |
473
|
|
|
|
474
|
|
|
foreach ($minimumRequiredParameters as $parameterName => $isParamPresent) { |
475
|
|
|
if (in_array($parameterName, array_keys($this->singleParameters))) { |
476
|
|
|
$minimumRequiredParameters[$parameterName] = true; |
477
|
|
|
} |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
return !in_array(false, $minimumRequiredParameters, true); |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Sets a parameter action to the value specified by the method call. |
485
|
|
|
* |
486
|
|
|
* @param $parameter |
487
|
|
|
* @param $action |
488
|
|
|
* @return $this |
489
|
|
|
*/ |
490
|
|
|
private function setParameterActionTo($parameter, $action) |
491
|
|
|
{ |
492
|
|
|
$actionConstant = $this->getParameterClassConstant( |
493
|
|
|
'TheIconic\Tracking\GoogleAnalytics\Parameters\EnhancedEcommerce\\' |
494
|
|
|
. $parameter . 'Action::ACTION_' . strtoupper($action), |
495
|
|
|
$parameter . ' action ' . $action . ' does not exist, check spelling' |
496
|
|
|
); |
497
|
|
|
|
498
|
|
|
$function = 'set' . $parameter . 'Action'; |
499
|
|
|
|
500
|
|
|
$this->$function($actionConstant); |
501
|
|
|
|
502
|
|
|
return $this; |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* Gets a contant from a class dynamically. |
507
|
|
|
* |
508
|
|
|
* @param $constant |
509
|
|
|
* @param $exceptionMsg |
510
|
|
|
* @return mixed |
511
|
|
|
* @throws \BadMethodCallException |
512
|
|
|
*/ |
513
|
|
|
private function getParameterClassConstant($constant, $exceptionMsg) |
514
|
|
|
{ |
515
|
|
|
if (defined($constant)) { |
516
|
|
|
return constant($constant); |
517
|
|
|
} else { |
518
|
|
|
throw new \BadMethodCallException($exceptionMsg); |
519
|
|
|
} |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
/** |
523
|
|
|
* Sets the value for a parameter. |
524
|
|
|
* |
525
|
|
|
* @param $methodName |
526
|
|
|
* @param array $methodArguments |
527
|
|
|
* @return $this |
528
|
|
|
* @throws \InvalidArgumentException |
529
|
|
|
*/ |
530
|
|
|
private function setParameter($methodName, array $methodArguments) |
531
|
|
|
{ |
532
|
|
|
$parameterClass = substr($methodName, 3); |
533
|
|
|
|
534
|
|
|
$fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName); |
535
|
|
|
|
536
|
|
|
$parameterIndex = $this->getIndexFromArguments($methodArguments); |
537
|
|
|
|
538
|
|
|
/** @var SingleParameter $parameterObject */ |
539
|
|
|
$parameterObject = new $fullParameterClass($parameterIndex); |
540
|
|
|
|
541
|
|
|
if (!isset($methodArguments[0])) { |
542
|
|
|
throw new \InvalidArgumentException( |
543
|
|
|
'For Analytics object, you must specify a value to be set for ' . $methodName |
544
|
|
|
); |
545
|
|
|
} else { |
546
|
|
|
$parameterObject->setValue($methodArguments[0]); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
$this->singleParameters[$parameterObject->getName()] = $parameterObject; |
550
|
|
|
|
551
|
|
|
return $this; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
/** |
555
|
|
|
* Adds an item to a compund parameter collection. |
556
|
|
|
* |
557
|
|
|
* @SuppressWarnings(PHPMD.LongVariable) |
558
|
|
|
* |
559
|
|
|
* @param $methodName |
560
|
|
|
* @param array $methodArguments |
561
|
|
|
* @return $this |
562
|
|
|
* @throws \InvalidArgumentException |
563
|
|
|
*/ |
564
|
|
|
private function addItem($methodName, array $methodArguments) |
565
|
|
|
{ |
566
|
|
|
$parameterClass = substr($methodName, 3); |
567
|
|
|
|
568
|
|
|
$fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName); |
569
|
|
|
|
570
|
|
|
if (!isset($methodArguments[0])) { |
571
|
|
|
throw new \InvalidArgumentException( |
572
|
|
|
'You must specify a ' . $parameterClass . ' to be add for ' . $methodName |
573
|
|
|
); |
574
|
|
|
} else { |
575
|
|
|
$parameterObject = new $fullParameterClass($methodArguments[0]); |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
$collectionIndex = $this->getIndexFromArguments($methodArguments); |
579
|
|
|
|
580
|
|
|
if (isset($this->compoundParametersCollections[$parameterClass . $collectionIndex])) { |
581
|
|
|
$this->compoundParametersCollections[$parameterClass . $collectionIndex]->add($parameterObject); |
582
|
|
|
} else { |
583
|
|
|
$fullParameterCollectionClass = $fullParameterClass . 'Collection'; |
584
|
|
|
|
585
|
|
|
/** @var CompoundParameterCollection $parameterObjectCollection */ |
586
|
|
|
$parameterObjectCollection = new $fullParameterCollectionClass($collectionIndex); |
587
|
|
|
|
588
|
|
|
$parameterObjectCollection->add($parameterObject); |
589
|
|
|
|
590
|
|
|
$this->compoundParametersCollections[$parameterClass . $collectionIndex] = $parameterObjectCollection; |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
return $this; |
594
|
|
|
} |
595
|
|
|
|
596
|
|
|
/** |
597
|
|
|
* Gets the value for a parameter. |
598
|
|
|
* |
599
|
|
|
* @param $methodName |
600
|
|
|
* @param array $methodArguments |
601
|
|
|
* @return $this |
602
|
|
|
* @throws \InvalidArgumentException |
603
|
|
|
*/ |
604
|
|
|
private function getParameter($methodName, array $methodArguments) |
605
|
|
|
{ |
606
|
|
|
$parameterClass = substr($methodName, 3); |
607
|
|
|
|
608
|
|
|
$fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName); |
609
|
|
|
|
610
|
|
|
// Handle index arguments |
611
|
|
|
$parameterIndex = ''; |
612
|
|
|
if (isset($methodArguments[0]) && is_numeric($methodArguments[0])) { |
613
|
|
|
$parameterIndex = $methodArguments[0]; |
614
|
|
|
} |
615
|
|
|
|
616
|
|
|
// Handle compoundParametersCollections |
617
|
|
|
if (isset($this->compoundParametersCollections[$parameterClass . $parameterIndex])) { |
618
|
|
|
// If compoundParametersCollections contains our Objects, return them well-formatted |
619
|
|
|
return $this->compoundParametersCollections[$parameterClass . $parameterIndex]->getReadableItems(); |
|
|
|
|
620
|
|
|
} else { |
621
|
|
|
$fullParameterCollectionClass = $fullParameterClass . 'Collection'; |
622
|
|
|
|
623
|
|
|
// Test if the class Collection exist |
624
|
|
|
if(class_exists($fullParameterCollectionClass)){ |
625
|
|
|
return null; |
626
|
|
|
} |
627
|
|
|
// If not, it's a SingleParameter Object, continue the magic |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
/** @var SingleParameter $parameterObject */ |
631
|
|
|
$parameterObject = new $fullParameterClass($parameterIndex); |
632
|
|
|
|
633
|
|
|
if(!array_key_exists($parameterObject->getName(), $this->singleParameters)){ |
634
|
|
|
return null; |
635
|
|
|
} |
636
|
|
|
$currentParameterObject = $this->singleParameters[$parameterObject->getName()]; |
637
|
|
|
|
638
|
|
|
return $currentParameterObject->getValue(); |
639
|
|
|
|
640
|
|
|
} |
641
|
|
|
|
642
|
|
|
/** |
643
|
|
|
* Gets the index value from the arguments. |
644
|
|
|
* |
645
|
|
|
* @param $methodArguments |
646
|
|
|
* @return string |
647
|
|
|
*/ |
648
|
|
|
private function getIndexFromArguments($methodArguments) |
649
|
|
|
{ |
650
|
|
|
$index = ''; |
651
|
|
|
if (isset($methodArguments[1]) && is_numeric($methodArguments[1])) { |
652
|
|
|
$index = $methodArguments[1]; |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
return $index; |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
/** |
659
|
|
|
* Gets the fully qualified name for a parameter. |
660
|
|
|
* |
661
|
|
|
* @param $parameterClass |
662
|
|
|
* @param $methodName |
663
|
|
|
* @return string |
664
|
|
|
* @throws \BadMethodCallException |
665
|
|
|
*/ |
666
|
|
|
private function getFullParameterClass($parameterClass, $methodName) |
667
|
|
|
{ |
668
|
|
|
if (empty($this->availableParameters[$parameterClass])) { |
669
|
|
|
throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class'); |
670
|
|
|
} else { |
671
|
|
|
return '\\TheIconic\\Tracking\\GoogleAnalytics\\Parameters\\' . $this->availableParameters[$parameterClass]; |
672
|
|
|
} |
673
|
|
|
} |
674
|
|
|
|
675
|
|
|
/** |
676
|
|
|
* Routes the method call to the adequate private method. |
677
|
|
|
* |
678
|
|
|
* @param $methodName |
679
|
|
|
* @param array $methodArguments |
680
|
|
|
* @return $this|AnalyticsResponse |
681
|
|
|
* @throws \BadMethodCallException |
682
|
|
|
*/ |
683
|
|
|
public function __call($methodName, array $methodArguments) |
684
|
|
|
{ |
685
|
|
|
$methodName = $this->fixTypos($methodName); |
686
|
|
|
|
687
|
|
|
if (preg_match('/^set(Product|Promotion)ActionTo(\w+)/', $methodName, $matches)) { |
688
|
|
|
return $this->setParameterActionTo($matches[1], $matches[2]); |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
if (preg_match('/^(set)(\w+)/', $methodName, $matches)) { |
692
|
|
|
return $this->setParameter($methodName, $methodArguments); |
693
|
|
|
} |
694
|
|
|
|
695
|
|
|
if (preg_match('/^(add)(\w+)/', $methodName, $matches)) { |
696
|
|
|
return $this->addItem($methodName, $methodArguments); |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
if (preg_match('/^(send)(\w+)/', $methodName, $matches)) { |
700
|
|
|
return $this->sendHit($methodName); |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
// Get Parameters |
704
|
|
|
if (preg_match('/^(get)(\w+)/', $methodName, $matches)) { |
705
|
|
|
return $this->getParameter($methodName, $methodArguments); |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class'); |
709
|
|
|
} |
710
|
|
|
|
711
|
|
|
/** |
712
|
|
|
* Fix typos that went into releases, this way we ensure we don't break scripts in production. |
713
|
|
|
* |
714
|
|
|
* @param string $methodName |
715
|
|
|
* @return string |
716
|
|
|
*/ |
717
|
|
|
private function fixTypos($methodName) |
718
|
|
|
{ |
719
|
|
|
// deprecated in v2, to be removed in v3 |
720
|
|
|
if ($methodName === 'setUserTiminCategory') { |
721
|
|
|
$methodName = 'setUserTimingCategory'; |
722
|
|
|
} |
723
|
|
|
|
724
|
|
|
return $methodName; |
725
|
|
|
} |
726
|
|
|
} |
727
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.