Version Description
Download this release
Release Info
Developer | chriscct7 |
Plugin | ![]() |
Version | 7.2.0 |
Comparing to | |
See all releases |
Code changes from version 7.2.1 to 7.2.0
- assets/css/admin-widget-settings.css +218 -218
- assets/images/plugin-pushengage.svg +19 -19
- assets/js/admin-widget-settings.js +68 -68
- assets/js/frontend-gtag.js +829 -829
- assets/js/popular-posts.js +33 -33
- gadwp.php +2 -2
- includes/admin/em-admin.php +25 -25
- includes/admin/notification-event-runner.php +189 -189
- includes/admin/notification-event.php +237 -237
- includes/admin/notifications/notification-audience.php +101 -101
- includes/admin/notifications/notification-bounce-rate.php +54 -54
- includes/admin/notifications/notification-events.php +17 -17
- includes/admin/notifications/notification-headline-analyzer.php +41 -41
- includes/admin/notifications/notification-mobile-device.php +53 -53
- includes/admin/notifications/notification-returning-visitors.php +53 -53
- includes/admin/notifications/notification-to-add-more-file-extensions.php +48 -48
- includes/admin/notifications/notification-to-setup-affiliate-links.php +54 -54
- includes/admin/notifications/notification-traffic-dropping.php +52 -52
- includes/admin/notifications/notification-upgrade-for-email-summaries.php +41 -41
- includes/admin/notifications/notification-upgrade-for-form-conversion.php +41 -41
- includes/admin/notifications/notification-upgrade-for-google-optimize.php +41 -41
- includes/admin/notifications/notification-upgrade-for-search-console.php +41 -41
- includes/admin/notifications/notification-upgrade-to-pro.php +42 -42
- includes/admin/notifications/notification-visitors.php +50 -50
- includes/admin/sharedcount.php +637 -637
- includes/admin/uninstall.php +26 -26
- includes/frontend/events/class-gtag-events.php +117 -117
- includes/frontend/tracking/class-tracking-gtag.php +486 -486
- includes/popular-posts/class-popular-posts-themes.php +850 -850
- includes/popular-posts/class-popular-posts.php +742 -742
- lite/includes/gutenberg/blocks/blocks.php +162 -162
- lite/includes/gutenberg/frontend.php +3 -3
- lite/includes/popular-posts/class-popular-posts-ajax.php +259 -259
- lite/includes/popular-posts/class-popular-posts-cache.php +131 -131
- lite/includes/popular-posts/class-popular-posts-inline.php +270 -270
- lite/includes/popular-posts/class-popular-posts-widget-sidebar.php +425 -425
- lite/includes/popular-posts/class-popular-posts-widget.php +262 -262
- readme.txt +2 -2
assets/css/admin-widget-settings.css
CHANGED
@@ -1,218 +1,218 @@
|
|
1 |
-
.exactmetrics-label-block,
|
2 |
-
.exactmetrics-radio-icons {
|
3 |
-
display: block;
|
4 |
-
}
|
5 |
-
|
6 |
-
.exactmetrics-radio-icons {
|
7 |
-
margin: 4px 0;
|
8 |
-
}
|
9 |
-
|
10 |
-
.exactmetrics-radio-icons * {
|
11 |
-
box-sizing: border-box;
|
12 |
-
}
|
13 |
-
|
14 |
-
.exactmetrics-radio-icons > label {
|
15 |
-
display: inline-block;
|
16 |
-
}
|
17 |
-
|
18 |
-
.exactmetrics-radio-icons input[type="radio"] {
|
19 |
-
visibility: hidden;
|
20 |
-
display: none;
|
21 |
-
}
|
22 |
-
|
23 |
-
.exactmetrics-wide-column {
|
24 |
-
display: -webkit-box;
|
25 |
-
display: -ms-flexbox;
|
26 |
-
display: flex;
|
27 |
-
border: 1px solid #b7c9d9;
|
28 |
-
border-radius: 5px;
|
29 |
-
width: 40px;
|
30 |
-
height: 40px;
|
31 |
-
padding: 10px 5px;
|
32 |
-
-ms-flex-flow: wrap;
|
33 |
-
flex-flow: wrap;
|
34 |
-
-webkit-box-pack: justify;
|
35 |
-
-ms-flex-pack: justify;
|
36 |
-
justify-content: space-between;
|
37 |
-
margin-right: 4px;
|
38 |
-
}
|
39 |
-
|
40 |
-
.exactmetrics-wide-column > span {
|
41 |
-
background: #99a1b2;
|
42 |
-
display: inline-block;
|
43 |
-
width: 8px;
|
44 |
-
height: 8px;
|
45 |
-
border-radius: 1px;
|
46 |
-
margin-bottom: 2px;
|
47 |
-
}
|
48 |
-
|
49 |
-
.exactmetrics-wide-column.exactmetrics-wide-column-two > span {
|
50 |
-
width: 12px;
|
51 |
-
}
|
52 |
-
|
53 |
-
.exactmetrics-radio-icons input[type="radio"]:checked + .exactmetrics-wide-column {
|
54 |
-
border: 2px solid #338eef;
|
55 |
-
background: #ecf4fe;
|
56 |
-
padding: 9px 4px;
|
57 |
-
}
|
58 |
-
|
59 |
-
.exactmetrics-radio-icons input[type="radio"]:checked + .exactmetrics-wide-column > span {
|
60 |
-
background: #338eef;
|
61 |
-
}
|
62 |
-
|
63 |
-
.exactmetrics-wide-column.exactmetrics-wide-column-one > span {
|
64 |
-
width: 100%;
|
65 |
-
}
|
66 |
-
|
67 |
-
.exactmetrics-field-description {
|
68 |
-
font-family: Helvetica Neue, serif;
|
69 |
-
font-style: italic;
|
70 |
-
font-weight: normal;
|
71 |
-
font-size: 13px;
|
72 |
-
line-height: 1.5%;
|
73 |
-
color: #545C66;
|
74 |
-
}
|
75 |
-
|
76 |
-
/** SELECT2 Styles **/
|
77 |
-
.select300-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select300-container .select300-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select300-container .select300-selection--single .select300-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select300-container .select300-selection--single .select300-selection__clear{position:relative}.select300-container[dir="rtl"] .select300-selection--single .select300-selection__rendered{padding-right:8px;padding-left:20px}.select300-container .select300-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select300-container .select300-selection--multiple .select300-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select300-container .select300-search--inline{float:left}.select300-container .select300-search--inline .select300-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select300-container .select300-search--inline .select300-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select300-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select300-results{display:block}.select300-results__options{list-style:none;margin:0;padding:0}.select300-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select300-results__option[aria-selected]{cursor:pointer}.select300-container--open .select300-dropdown{left:0}.select300-container--open .select300-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select300-container--open .select300-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select300-search--dropdown{display:block;padding:4px}.select300-search--dropdown .select300-search__field{padding:4px;width:100%;box-sizing:border-box}.select300-search--dropdown .select300-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select300-search--dropdown.select300-search--hide{display:none}.select300-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select300-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select300-container--default .select300-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select300-container--default .select300-selection--single .select300-selection__rendered{color:#444;line-height:28px}.select300-container--default .select300-selection--single .select300-selection__clear{cursor:pointer;float:right;font-weight:bold}.select300-container--default .select300-selection--single .select300-selection__placeholder{color:#999}.select300-container--default .select300-selection--single .select300-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select300-container--default .select300-selection--single .select300-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select300-container--default[dir="rtl"] .select300-selection--single .select300-selection__clear{float:left}.select300-container--default[dir="rtl"] .select300-selection--single .select300-selection__arrow{left:1px;right:auto}.select300-container--default.select300-container--disabled .select300-selection--single{background-color:#eee;cursor:default}.select300-container--default.select300-container--disabled .select300-selection--single .select300-selection__clear{display:none}.select300-container--default.select300-container--open .select300-selection--single .select300-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select300-container--default .select300-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select300-container--default .select300-selection--multiple .select300-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select300-container--default .select300-selection--multiple .select300-selection__rendered li{list-style:none}.select300-container--default .select300-selection--multiple .select300-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select300-container--default .select300-selection--multiple .select300-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select300-container--default .select300-selection--multiple .select300-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select300-container--default .select300-selection--multiple .select300-selection__choice__remove:hover{color:#333}.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-selection__choice,.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-search--inline{float:right}.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-selection__choice{margin-left:5px;margin-right:auto}.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-selection__choice__remove{margin-left:2px;margin-right:auto}.select300-container--default.select300-container--focus .select300-selection--multiple{border:solid black 1px;outline:0}.select300-container--default.select300-container--disabled .select300-selection--multiple{background-color:#eee;cursor:default}.select300-container--default.select300-container--disabled .select300-selection__choice__remove{display:none}.select300-container--default.select300-container--open.select300-container--above .select300-selection--single,.select300-container--default.select300-container--open.select300-container--above .select300-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select300-container--default.select300-container--open.select300-container--below .select300-selection--single,.select300-container--default.select300-container--open.select300-container--below .select300-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select300-container--default .select300-search--dropdown .select300-search__field{border:1px solid #aaa}.select300-container--default .select300-search--inline .select300-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select300-container--default .select300-results>.select300-results__options{max-height:200px;overflow-y:auto}.select300-container--default .select300-results__option[role=group]{padding:0}.select300-container--default .select300-results__option[aria-disabled=true]{color:#999}.select300-container--default .select300-results__option[aria-selected=true]{background-color:#ddd}.select300-container--default .select300-results__option .select300-results__option{padding-left:1em}.select300-container--default .select300-results__option .select300-results__option .select300-results__group{padding-left:0}.select300-container--default .select300-results__option .select300-results__option .select300-results__option{margin-left:-1em;padding-left:2em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-2em;padding-left:3em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-3em;padding-left:4em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-4em;padding-left:5em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-5em;padding-left:6em}.select300-container--default .select300-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select300-container--default .select300-results__group{cursor:default;display:block;padding:6px}.select300-container--classic .select300-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select300-container--classic .select300-selection--single:focus{border:1px solid #5897fb}.select300-container--classic .select300-selection--single .select300-selection__rendered{color:#444;line-height:28px}.select300-container--classic .select300-selection--single .select300-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select300-container--classic .select300-selection--single .select300-selection__placeholder{color:#999}.select300-container--classic .select300-selection--single .select300-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select300-container--classic .select300-selection--single .select300-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select300-container--classic[dir="rtl"] .select300-selection--single .select300-selection__clear{float:left}.select300-container--classic[dir="rtl"] .select300-selection--single .select300-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select300-container--classic.select300-container--open .select300-selection--single{border:1px solid #5897fb}.select300-container--classic.select300-container--open .select300-selection--single .select300-selection__arrow{background:transparent;border:none}.select300-container--classic.select300-container--open .select300-selection--single .select300-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select300-container--classic.select300-container--open.select300-container--above .select300-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select300-container--classic.select300-container--open.select300-container--below .select300-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select300-container--classic .select300-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select300-container--classic .select300-selection--multiple:focus{border:1px solid #5897fb}.select300-container--classic .select300-selection--multiple .select300-selection__rendered{list-style:none;margin:0;padding:0 5px}.select300-container--classic .select300-selection--multiple .select300-selection__clear{display:none}.select300-container--classic .select300-selection--multiple .select300-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select300-container--classic .select300-selection--multiple .select300-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select300-container--classic .select300-selection--multiple .select300-selection__choice__remove:hover{color:#555}.select300-container--classic[dir="rtl"] .select300-selection--multiple .select300-selection__choice{float:right;margin-left:5px;margin-right:auto}.select300-container--classic[dir="rtl"] .select300-selection--multiple .select300-selection__choice__remove{margin-left:2px;margin-right:auto}.select300-container--classic.select300-container--open .select300-selection--multiple{border:1px solid #5897fb}.select300-container--classic.select300-container--open.select300-container--above .select300-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select300-container--classic.select300-container--open.select300-container--below .select300-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select300-container--classic .select300-search--dropdown .select300-search__field{border:1px solid #aaa;outline:0}.select300-container--classic .select300-search--inline .select300-search__field{outline:0;box-shadow:none}.select300-container--classic .select300-dropdown{background-color:#fff;border:1px solid transparent}.select300-container--classic .select300-dropdown--above{border-bottom:none}.select300-container--classic .select300-dropdown--below{border-top:none}.select300-container--classic .select300-results>.select300-results__options{max-height:200px;overflow-y:auto}.select300-container--classic .select300-results__option[role=group]{padding:0}.select300-container--classic .select300-results__option[aria-disabled=true]{color:grey}.select300-container--classic .select300-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select300-container--classic .select300-results__group{cursor:default;display:block;padding:6px}.select300-container--classic.select300-container--open .select300-dropdown{border-color:#5897fb}
|
78 |
-
|
79 |
-
.select300-container {
|
80 |
-
display: block;
|
81 |
-
width: 100% !important;
|
82 |
-
}
|
83 |
-
|
84 |
-
.select300-container--default .select300-selection--multiple .select300-selection__choice {
|
85 |
-
border-radius: 20px;
|
86 |
-
background: #E2E4E7;
|
87 |
-
border: none;
|
88 |
-
color: #32373C;
|
89 |
-
padding-left: 8px;
|
90 |
-
font-family: Helvetica Neue, serif;
|
91 |
-
font-style: normal;
|
92 |
-
font-weight: normal;
|
93 |
-
font-size: 13px;
|
94 |
-
line-height: 24px;
|
95 |
-
}
|
96 |
-
|
97 |
-
.select300-container--default .select300-selection--multiple .select300-selection__choice__remove {
|
98 |
-
line-height: 1;
|
99 |
-
width: 16px;
|
100 |
-
height: 16px;
|
101 |
-
float: right;
|
102 |
-
display: block;
|
103 |
-
border-radius: 50%;
|
104 |
-
background-color: #555D66;
|
105 |
-
color: #E2E4E7;
|
106 |
-
text-align: center;
|
107 |
-
margin: 4px 0px 4px 8px;
|
108 |
-
font-size: 14px;
|
109 |
-
box-sizing: border-box;
|
110 |
-
padding-top: 0;
|
111 |
-
padding-left: 0;
|
112 |
-
}
|
113 |
-
|
114 |
-
.select300-container--default .select300-selection--multiple .select300-selection__choice__remove:hover {
|
115 |
-
background-color: #333;
|
116 |
-
color: #E2E4E7;
|
117 |
-
}
|
118 |
-
|
119 |
-
.exactmetrics-widget-theme-preview {
|
120 |
-
background: #F0F2F4;
|
121 |
-
border-radius: 5px;
|
122 |
-
padding: 8px 8px 8px 18px;
|
123 |
-
display: flex;
|
124 |
-
font-family: Helvetica Neue, serif;
|
125 |
-
font-style: normal;
|
126 |
-
font-weight: normal;
|
127 |
-
font-size: 14px;
|
128 |
-
line-height: 1;
|
129 |
-
color: #32373C;
|
130 |
-
align-items: center;
|
131 |
-
justify-content: space-between;
|
132 |
-
}
|
133 |
-
|
134 |
-
.exactmetrics-widget-theme-preview-icon,
|
135 |
-
.exactmetrics-products-theme-preview-icon {
|
136 |
-
width: 74px;
|
137 |
-
height: 46px;
|
138 |
-
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAxAAAAEqCAMAAACyWUYtAAABBVBMVEUAAADw6v6AUPeEU/bw6f7w6v7v5P/w6v/v6vzy6/9lKPWEU/jw6/7v6fzw6/5kKPVlJ/ZlKPZoKPOEU/fw6v7Rv/xkJ/VlKPbx6/9lKPaEU/eEU/fv6P3w6/7w6v7Rv/xkKPVkJvTPv//Pv/dwIPNgIO/v6f2EU/jw6v7Rv/xkJ/RmKPbv5//Sv/zQv/zw6v5lKPWEU/fRv/x5Qvbe0f1uNPbt5v50PfbTwvzTwfyATffs5P3ay/zi1/3NufuIWPdoLPWMXvjWxfyRZPjczv3YyPzNufy8ovt2P/bErfvk2v3g0/1xOfZsMvXo3v23mvt4Q/bKtfymgvmfePmujvp7RvaCUPf1uE5qAAAAL3RSTlMA3yDvr4AQz2Bf369vUK/vr2Agv+/vz7+PgO6+kO/ur29QICAQEI/vv76QjyC/v+TVgYYAAAyJSURBVHja7N3PTttAEMfxweZPi6FA0hJIVFVqizhVM1uFSyWDzAGSSyslff9nqZpDpCRu5djr9azn93mDkfYLsrye0Mrx2eEBd+7k8C158vV2JGpcXxFE5fwjK3HgJ4nBqahyOiCIxw0rckQeKOtB5PSOIBZHrMoNNXYl6twSROINK3NOTV2LOiOCSCh4mt70/pgaEoUI4qDuHwTzGYKAzrxjdQ4RBHTmhNU5oIZYIYI4/nCxQgjCBlGol4eHFSJAEAgCQSAIBYeHFSJAEAgCQSAIBYeHFSJAEAgCQSAIBYeHFSKIAyuEmaAqBGF0JiiHIIzOBOUQhNGZoByCMDoTlEMQRmeCcgjC6EwQCG95fJLAnuYIovquKdqWDFMXQpaQCbxpLh2YI4jKu6Z2ekhdIGMbRfCmmXTgAUFU3jVFWzIXzIQs4A3P0okpgqi6a4q2uHDGZAFveJROvLQcRL4sXEiLnLf52TXVaRCOLLAQRF64wIrcdxCygiB2IYi9g1i44JYIIlIWgnDhFQgiUgiiHQiigsHoQvZzOWjzDUyWIIg1BBE8iMGF7O1i0OYbmHGCINYQROggLqWGUatvYCYIYg1BhA5C6rhodfIxglhDEFEEIe1OjiDWEASC2AliKp14RhB1g0jdfyCIpkHwg3RgxgiibhBDF0xmMYheXv92lcQZRLjr32liMQieh/9A6IURRO0gKMlcCOkkIZNBaOA7iMJVEWkQEZNaNp+eEESNIJYuuAWCaDuIoWtBZiKIPl//jpnU0ubTU5qYCILzhQupWOaMINoKor2np3SS9PNzS1YIQXgLohz2MtmaCUEgCMyEIBAEgkAQqoIIsLnvxyuCqB9EiM19WUKlDAYxlxB+IwjdVzfG5UUYDGImQfxEEJ6CyFwrJlTGXhDPEsYrgtD9PcSYSpkL4lF8URWEz819i9xCEI5KqQqiydNTllgOwu/VjSJHEBqCaPb0dJ8YDmLhvFoiCA1BZK6RoeEgnF8FgtAQhGvmHkF4gyB6EIRDEAgCQSAIBIEgEASCQBAIAkEgCARhJoiR/IUgAgcxlTDmCGJPt7Lyr819BoNIAwQRbHPfFEHs6e5UVgJt7stol7IgGk6eGb7+3Ycgwv5wexrB9e8kbWPCLjb3zX4xgqjh6lrCbO5LJ1F8INRg8nSYWLoqzVuKfgTRO1IDvqnWt7lvgSAQRHUKg+jD9e8+QhA92NxXLHNGEAhiDwqDUIAAQSAIBIEgFBweVogAQSAIBIEgFBweVojAdxBfvn347tenz/08PKwQwR/27Ca1cSAIwGgJLNkG2wnGJllkMCSbBMIU6P6Hm8X8wGxCEkuoJL93g4L6aKl74CBezv3gzs+LXJ4sKBg4iEs/grdFLk8WFAwcRD+G8yKXJwsK5hBEv8jlyYICQQhCEB+5uyqIcz+GaLKctSBuw8N3eriPP372I7jEIctZCeI2HL9xRNwdR7523WU5W0HciOP9V3N4OMY/L5ehc3h7juhOWUzj9Z0J7bOYbVzrNctZB3PxlKW0cbU2y9kGs1Fqf57iel25q7MmmJFNmQU67WMI72UG+q15D2Zlc1jn5JrDrhtsoALz/PXadgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwA3rdqsmJ7debQOmt/+RRTSSYHKPWUgbMKk2S3kMmNAmi9kHTKfA3/T/Tl3AZy3+gMjcBUzlkOWsAj5v4V9MmU3AVLKg4Bd7d9DaNhCEYdi3QmhpcgnkUhJoTznMyLUiRzFY4CY4YAVd7P//UypoVDzbdFf2yuvR7vechcAoL7KtmRh6QhAAexAEwB4EAbAHQQDsQRAAexAEwCmRabbMOaTVDEGAHmSY5RxYPkMQoAYZVhzcEkGAGmTg8HIEAWooCIIRBHbf1SABQWiG3fcPIIhkYff9IwgiVdh9/xCCSJS61cZId99JQBBqKfg0LX2Lc/edBAShlbobxFC7799vLy/47K4vrxDEqMS6+373lZW4uEIQI/KJ1Bli9/2eFblBEONBCk283bAq9whiNEihia8rVuYOQYwFKTTxpeDTtPT1B4IYCVIouhsE8y2CGAlSaOLpktW5jDeIyCZDSaGJp2tW5yLaIGKbDCWFJp5YoViDiG4ylCT77vtqRk4IIqUg4psMJcG1+567i0AQCQWhbvDnS+jd9yW5IIiEglDwadr8VaTAQ5g5uSCIdIJQd4Mg+hw4CCYXBJFOEDFOhpKAIDoIItHJUBIQRAdBJPqdPQkIooMgEEQLQXQQBIJoIYgOgkAQrXSCqH+W2SDKpkYQiiCIY4KottmAmgpBqIEgjgiiKrNBlRWC0AJBHBFEkw1siyBaUfwqEhlytokjiDobXM1WiQQRw68ikWHJVityUx9Ekw2uYatEgojhV5FISGP8u8wGV7JVIkFwePnp3wb+P/N8GceCUHYCbIUgOqN7TRogiD4U/vGw2+hekwaBg9iuN5uiKREEgkAQbQ41/7EpEQSCSD6Igv+qSgSBIEihgEEUvKcqEQSCUChcEA0L1Q5BeD/VtRvda9IgXBAVSwWC8HuqG9wKQQwYxJYN1Q5BYHRjXxTzWeyQdTZs2iIIz6e6IeXLGSHyAYOo2VQgiMTfXpAQx3wWWyEIBKH7m7N8LEGUmwZBIIh/qL9ObGX9DNHYeqiYCwSBIEzqrxM7ZJ01m0prD60CQSAIg/rrxA5ZZ1exVDt6aBUIAkFI6q8TO4jJDaF09dAqjgoCT3V7QRBnDcK8RRS2HuxHsQOe6vaCIFrnC0L+odt7cBzHDlE+8CHT0+Jx6uPXkzyX+/iz/9eNUzjn+He54XfV2taDUBweRBJPdZ8ep57mT/Jc7uMxnzVEEDKJmrmqi521B1cR7JDE24vF1NviwHMtMLoRbKda9iAVCKJFhqm/+YHnmmM+K1wQsgepQBCWIDwcei58URAwCNmDVCAIBNGHguvEDsf2IBUIggzzAYOYI4jTBbF+eaOQXtdpBvE89bY48FwLEhBEnyDWbxTY2zrJIB68bxGPD+JcfY4XEESfIF4puJckg6CHhV8Ozw/iXH2OlxBEnyAovDc2RLmrSwrhNakMglhIZXRDAbymkQYRw64uKYT5rJEGweHlJCCIVOazWEAQ77APkep8FoL43c7drjQOhFEAHqF+4kcFEQQRhV1/+OedzkLrurRgqS22xRDo/V/LrhC6k2yWppmanLw5zx3M0IMyPacMBNK377X3sxgIBgIpELXXUWzGh1SNgagJA1EkEFOp3HtbA9FfjJ17m/ySerCf1djqht1WIwIxT95RnodSC/azipX73qVKH6NsHtryqxtDtzaXOrCfFfozNEEG/NUNT/qd/bkvJeAFQkM/qxGB0FjdmDjPQsrACwSAVgRCw1ZXMsbOM5Yyav/wCKB2BALA1z5RytYQz4SAgcgHd9GSwkAk4M7EQOSr9l+mN9ka4pkQMBD54C5aMhbOM5GtIZ4JQXWBePkR5IWB8KTf2X9qeXYFsPNADKLYhYhee2uvs5HbZLVsZyBk7taGUgLimQDsOhCD2AWavq7zMHIFxMt2BkKGz8nfh7mUgnim5vezbMbKBZv1EpErJGppIKQ/GTs3XvSlJMAzNb+fZTNcuGkv4YqJbYbKra4AYj+rkkC4LQPhbIbKra4AYj+roYHQsNUVQOxnbQ5E7ML1ElNXjM1QudUVQOxnbQ5E5IJFvcTMFbKyGSqniQKIdZQqnl1Hf59dp66AeMlAlAHw4ZEUnYGwg5ULMZr5X8xFbpM4WtoslVtdAcR+1r8sIJVb3T2Bc8h+VkMDoWGrey5wOuxnNTQQGra6pwLnmP2spgYCgAl0cCVg9gz7WQxEaSbUmYA5NuxnMRClmWC3AmXfGL6cMRClmXD7AuTWMBB5Tiyca5UX/ekI5u316swwELm6Fk5X5UUnkTg/lNrtnZ8eGAYi372Fc6nyojUSQCbQ9wsL5kTnRWskgEyoBwvmUudWVyMBZII9WSg3Sre6GsG8Efj9rHA3FsiT1q2uRhr7WZ8uYd5eLx7UbnU10tjPSiLRvba1O+nef9O71dVIYz8LkqTo2OqqpLCfBUlSdEwTddLXz4IkKQwEMKh+1qNRSlJ0bHW1wuln3Z0ZrSRFx1ZXL139LEiSomOrS8StLtEf3OoSebjVJTKGLUqiTwwEkYeBIPIwEEQeBoLIw0AQeRgIolzc6hLtXkfgdAzRdrjVJfoSB3cCRulWlxqCW10i36NA0brVpcbgVpeIW12i/zrqIGx1O5q3utQIvwFN0uiXuNQl8wAAAABJRU5ErkJggg==);
|
139 |
-
background-repeat: no-repeat;
|
140 |
-
background-position: 0 0;
|
141 |
-
background-size: 392px;
|
142 |
-
display: inline-block;
|
143 |
-
}
|
144 |
-
|
145 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-beta {
|
146 |
-
background-position-x: -212px;
|
147 |
-
}
|
148 |
-
|
149 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-charlie {
|
150 |
-
background-position-x: -106px;
|
151 |
-
}
|
152 |
-
|
153 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-delta {
|
154 |
-
height: 43px;
|
155 |
-
background-position: -318px 0;
|
156 |
-
}
|
157 |
-
|
158 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-echo {
|
159 |
-
height: 76px;
|
160 |
-
background-position: 0 -73px;
|
161 |
-
}
|
162 |
-
|
163 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-foxtrot {
|
164 |
-
background-position: -106px -90px;
|
165 |
-
height: 41px;
|
166 |
-
}
|
167 |
-
|
168 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-golf {
|
169 |
-
background-position: -212px -83px;
|
170 |
-
height: 56px;
|
171 |
-
}
|
172 |
-
|
173 |
-
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-hotel {
|
174 |
-
height: 50px;
|
175 |
-
background-position: -318px -86px;
|
176 |
-
}
|
177 |
-
|
178 |
-
.exactmetrics-products-theme-preview-icon {
|
179 |
-
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlAAAACcCAMAAACHiWWRAAAA3lBMVEUAAABlKPX///9oKPNlJ/ZkKPVkKfRlKPZlKPVlKPbRv/zw6v7Pv/vw6/7w6v7w6v7w6/7v6vzy6//w5f/w6v5lJ/Xw6f5lKPXv6fxlH/Pw6f7w6v7Rv/zRv/xkKPVmJ/VlJvZjJvLw6/7w6v/w6v9jJ/NmKfbv6PxlKPXw6v7Rv/yEU/f///95QvZmKfXs5f7Twvx/TPd0PfZuNPbZyv1pLfXbzf11PvZyOvbf0v3e0P2RZPiIWPfNuvzKtftsMvX18v7+/v+NYfh7Rva2mfq5nfuCUPe+pPuvkPqvkPnAI7BMAAAAKHRSTlMA/gEgr+/uv99g798gr5CAb2BfEO/PsIBQEN/Pv69wj1BQ78/OkI5P5JBZSwAAB1NJREFUeNrs3EtqAkEYReFqYhJF8o4vBPMYhFuIgjhTwUH2v6eM09GyUOmckvut4MJ/aHVgByvYVVso7atgJYP1JLVHwcrVEc4gWLl6wrkNVi7xVMHKJR4HVTLxOKiSicdBlUw8Dqpk4nFQJROPgyqZeBxUycQDDurlsd+N/27cfw5Y4uEGNfyMEF1sUuLBBnUfQR4Ck3ioQT1ElPuAJB5oUE8RZhiIxAMNCvBt/LfXlwAkHmZQuAdUjI8BSDzMoO4iTj8AiYcZ1DjidAOQeJhBRaAAJB4H5aAcVA4HlcVB5XJQWRxULgeVxUHlclBZHFQDEkGNJi3Av797rY6DOi2o1WapJq1XO4N6vxFEu+OgTghqtVTDlqsdQb2Joxo4qOODWqtxm79BDYTy5aCODkrNW8Ya3KtOqg8HVVBQijW8dzFdj8TjoPaJNbQHlFRNxOOg9ok1LeEAJzmovWIN8OVeuA9hOaj9CBsOqMTjoHZzUEeqiD89EcckbEhyULkYxyRsSHJQuRjHJGxIclC5GMckbEhyULkYxyRsSHJQuRjHJGxIclC5GMckbEhyULkYxyRsSKIGRUQ4JmFDkoO6/KC2s8X0LBazrQ5xUJce1Px7ekazudIc1IUHNV9Mz2oxV5KDuvCgfti5tyVFYSgKw1YB8iqrxViFaAXPjrb2zPu/0DCtJbZj04GEmMD67+HquwnZG5EY7ojKCKrboHaJ8XaoiqC6DUokxhOoiqC6DSpNjJeiKoLqNqikhVAVQREUQalFUPgP1FHmeS5SgnIi70Edd7iUpwTlQL6DmuLWPCWo1+c5qCnKClEE9fL8BiXwpfmZoGrWT1D5+3ak1unQK1BBPES9wmBwS/1p9bd7ASrfjpTbHHoEKmgAIrqJUni6wdt9APV7VKOPHoEK0aB4cC1EC8U+gBrVadMjUGhS1OqPjaPOgRoR1A+1CcqNeW5boNJcEBRBAVszoNI5IAmKoPBex9OpyhMgCYqgtD8blJ4ASVC9B4X8jyqnj588AZKgeg/qoZLBeY6y0kqVJ0AS1GcRzOc7qHsoqp4AWR/U5M3BNEHFaKHQc1BJmuPaRNUTIAmqKIhgvKEXVy+PPWjJd8BkNz0rewIkQRUFIcw2jP24HH4sqUjJEyAJ6lI/x1ce0vcESIL6jKCKDHgCJEH9i6CKTHgCJEEV9ROUmO3HOm0EniQIajDoJSixH2u2fy6KoAa9BLUZazfDs44E1TqoDJZSBzUZ67fHs6YE1TqoNay3sgDqF0HdMrL1EgaKoBYZLJctCMo6KP2tlyhQAlWIWsFm2XrxRlAvARVCq/gbUA5GUFZAQa+IoAjKJCgQlFFQy3UGm62WBGUK1N5BUEv7h5clQZkBhZk+qA0Ao6BWsN6aoBSzc/WiB8qBG4WMoAyBgtjocZoJAN6DAkEp1nx8ZQrlCOqSqa0XRVBOnF5QRlB3ubX1EqqAcuP0glsEdZ9TWy/DQAWUG6cXXCOorzm09TKMA3fnoTKCUsvL8RW8IB9BuTA3RlAdAuXC3BhBGQeVCq3SpqDcmBsjqKc1+E/56ZCYqTEoJ+bG/rJzRy0Nw0AAxzOtYy19HWPQTn0Q7g5mMgjBFzfQqd//GwmzL7sVasPVXW1+r4V7GH/KGpKkoFrFXDj2+nb1oBRIQbWKuqf8KwU1kqA0fL0A03obuawdpKAmc+oFqIVwUFuYYFBlVZCsuhzDqZe/COoA0wuqLEhcUeI5FV8vwOzpkvgLanpB1TSAChUC5kgXPmT/QT0DwOSCoiEUqFD3ssH+U7Kn91NPKSgRqBAw/J7y/fEFDtud0Ntpe4BGr6Csd9RfsNhIQQ1Hw1oY9AzKOoriBIuK3HNpGgXFSUFF6AwqUCSPYuL2XGamUdEAalQI9LkIimI5FBO153J+O/CygUKgj1xQhGJ677lkOy3LWjqnqhzlqRdZYw5KIeSsdyQpWD6bPx9lUI56m2ZQ1pEwZ/ls/nyMQXmKFPDHVIIKJM53zPbILECdJZ5RsmygETIkz3XMdshkoE6GnA3Un/MWGymoeF2zkdmANrMcFTIa4RkdQa3vQJnFDSpkNELGkbyu2ciYR9BllqegYoPyJC50zA7IGPMEqqxMCmrMywbGmBUocm9SUL+GnA2yOXnLZ/PnrT9UrmbtYP5gUlBtxnPhmDnJsyVc3SLbrE0K6l8EpUoKKgX13a7dpSAIRVEU3vga9qeE2GNBHJ98kOY/tAZgN66CtLutbwiHhaDbTYNKbZ75/2SWeSeCWhdU+uUld1wp9E4EtTao55A0RYZC70RQa4Ma0sbIUOidCGqDoIbIUOidpF3YuckPQeWqw85FfmZBjQT13jHsnOVnFtT0abvMUGxQTRtmehnis0G2Lsw4PqBmQSU3z3H68w+b0j6sHOSI6WWBQxjZyxJBLXHqw0TbyRNBLXOqr/F1u/rYyBRBgaDgi6BAUPBVGW6ed+FnVWyeEJsnbLF5QmLzhK2KzRMSmyd8GW2eD6EEbJ4o2AuunoM0UoU65AAAAABJRU5ErkJggg==');
|
180 |
-
width: 74px;
|
181 |
-
height: 39px;
|
182 |
-
background-size: 188px;
|
183 |
-
}
|
184 |
-
|
185 |
-
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-alpha {
|
186 |
-
background-position: 0 0;
|
187 |
-
}
|
188 |
-
|
189 |
-
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-beta {
|
190 |
-
background-position: -114px 0;
|
191 |
-
height: 65px;
|
192 |
-
}
|
193 |
-
|
194 |
-
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-charlie {
|
195 |
-
background-position: 0 -102px;
|
196 |
-
height: 50px;
|
197 |
-
}
|
198 |
-
|
199 |
-
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-delta {
|
200 |
-
background-position: -114px -102px;
|
201 |
-
height: 78px;
|
202 |
-
}
|
203 |
-
|
204 |
-
.exactmetrics-pro-pill {
|
205 |
-
font-style: normal;
|
206 |
-
font-weight: bold;
|
207 |
-
font-size: 11px;
|
208 |
-
background: #1EC185;
|
209 |
-
border-radius: 5px;
|
210 |
-
color: #fff;
|
211 |
-
padding: 3px 8px;
|
212 |
-
margin-left: 8px;
|
213 |
-
}
|
214 |
-
|
215 |
-
.select300-container--disabled {
|
216 |
-
margin-top: 10px;
|
217 |
-
opacity: 0.6;
|
218 |
-
}
|
1 |
+
.exactmetrics-label-block,
|
2 |
+
.exactmetrics-radio-icons {
|
3 |
+
display: block;
|
4 |
+
}
|
5 |
+
|
6 |
+
.exactmetrics-radio-icons {
|
7 |
+
margin: 4px 0;
|
8 |
+
}
|
9 |
+
|
10 |
+
.exactmetrics-radio-icons * {
|
11 |
+
box-sizing: border-box;
|
12 |
+
}
|
13 |
+
|
14 |
+
.exactmetrics-radio-icons > label {
|
15 |
+
display: inline-block;
|
16 |
+
}
|
17 |
+
|
18 |
+
.exactmetrics-radio-icons input[type="radio"] {
|
19 |
+
visibility: hidden;
|
20 |
+
display: none;
|
21 |
+
}
|
22 |
+
|
23 |
+
.exactmetrics-wide-column {
|
24 |
+
display: -webkit-box;
|
25 |
+
display: -ms-flexbox;
|
26 |
+
display: flex;
|
27 |
+
border: 1px solid #b7c9d9;
|
28 |
+
border-radius: 5px;
|
29 |
+
width: 40px;
|
30 |
+
height: 40px;
|
31 |
+
padding: 10px 5px;
|
32 |
+
-ms-flex-flow: wrap;
|
33 |
+
flex-flow: wrap;
|
34 |
+
-webkit-box-pack: justify;
|
35 |
+
-ms-flex-pack: justify;
|
36 |
+
justify-content: space-between;
|
37 |
+
margin-right: 4px;
|
38 |
+
}
|
39 |
+
|
40 |
+
.exactmetrics-wide-column > span {
|
41 |
+
background: #99a1b2;
|
42 |
+
display: inline-block;
|
43 |
+
width: 8px;
|
44 |
+
height: 8px;
|
45 |
+
border-radius: 1px;
|
46 |
+
margin-bottom: 2px;
|
47 |
+
}
|
48 |
+
|
49 |
+
.exactmetrics-wide-column.exactmetrics-wide-column-two > span {
|
50 |
+
width: 12px;
|
51 |
+
}
|
52 |
+
|
53 |
+
.exactmetrics-radio-icons input[type="radio"]:checked + .exactmetrics-wide-column {
|
54 |
+
border: 2px solid #338eef;
|
55 |
+
background: #ecf4fe;
|
56 |
+
padding: 9px 4px;
|
57 |
+
}
|
58 |
+
|
59 |
+
.exactmetrics-radio-icons input[type="radio"]:checked + .exactmetrics-wide-column > span {
|
60 |
+
background: #338eef;
|
61 |
+
}
|
62 |
+
|
63 |
+
.exactmetrics-wide-column.exactmetrics-wide-column-one > span {
|
64 |
+
width: 100%;
|
65 |
+
}
|
66 |
+
|
67 |
+
.exactmetrics-field-description {
|
68 |
+
font-family: Helvetica Neue, serif;
|
69 |
+
font-style: italic;
|
70 |
+
font-weight: normal;
|
71 |
+
font-size: 13px;
|
72 |
+
line-height: 1.5%;
|
73 |
+
color: #545C66;
|
74 |
+
}
|
75 |
+
|
76 |
+
/** SELECT2 Styles **/
|
77 |
+
.select300-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select300-container .select300-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select300-container .select300-selection--single .select300-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select300-container .select300-selection--single .select300-selection__clear{position:relative}.select300-container[dir="rtl"] .select300-selection--single .select300-selection__rendered{padding-right:8px;padding-left:20px}.select300-container .select300-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select300-container .select300-selection--multiple .select300-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select300-container .select300-search--inline{float:left}.select300-container .select300-search--inline .select300-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select300-container .select300-search--inline .select300-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select300-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select300-results{display:block}.select300-results__options{list-style:none;margin:0;padding:0}.select300-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select300-results__option[aria-selected]{cursor:pointer}.select300-container--open .select300-dropdown{left:0}.select300-container--open .select300-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select300-container--open .select300-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select300-search--dropdown{display:block;padding:4px}.select300-search--dropdown .select300-search__field{padding:4px;width:100%;box-sizing:border-box}.select300-search--dropdown .select300-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select300-search--dropdown.select300-search--hide{display:none}.select300-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select300-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select300-container--default .select300-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select300-container--default .select300-selection--single .select300-selection__rendered{color:#444;line-height:28px}.select300-container--default .select300-selection--single .select300-selection__clear{cursor:pointer;float:right;font-weight:bold}.select300-container--default .select300-selection--single .select300-selection__placeholder{color:#999}.select300-container--default .select300-selection--single .select300-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select300-container--default .select300-selection--single .select300-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select300-container--default[dir="rtl"] .select300-selection--single .select300-selection__clear{float:left}.select300-container--default[dir="rtl"] .select300-selection--single .select300-selection__arrow{left:1px;right:auto}.select300-container--default.select300-container--disabled .select300-selection--single{background-color:#eee;cursor:default}.select300-container--default.select300-container--disabled .select300-selection--single .select300-selection__clear{display:none}.select300-container--default.select300-container--open .select300-selection--single .select300-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select300-container--default .select300-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select300-container--default .select300-selection--multiple .select300-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select300-container--default .select300-selection--multiple .select300-selection__rendered li{list-style:none}.select300-container--default .select300-selection--multiple .select300-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select300-container--default .select300-selection--multiple .select300-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select300-container--default .select300-selection--multiple .select300-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select300-container--default .select300-selection--multiple .select300-selection__choice__remove:hover{color:#333}.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-selection__choice,.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-search--inline{float:right}.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-selection__choice{margin-left:5px;margin-right:auto}.select300-container--default[dir="rtl"] .select300-selection--multiple .select300-selection__choice__remove{margin-left:2px;margin-right:auto}.select300-container--default.select300-container--focus .select300-selection--multiple{border:solid black 1px;outline:0}.select300-container--default.select300-container--disabled .select300-selection--multiple{background-color:#eee;cursor:default}.select300-container--default.select300-container--disabled .select300-selection__choice__remove{display:none}.select300-container--default.select300-container--open.select300-container--above .select300-selection--single,.select300-container--default.select300-container--open.select300-container--above .select300-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select300-container--default.select300-container--open.select300-container--below .select300-selection--single,.select300-container--default.select300-container--open.select300-container--below .select300-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select300-container--default .select300-search--dropdown .select300-search__field{border:1px solid #aaa}.select300-container--default .select300-search--inline .select300-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select300-container--default .select300-results>.select300-results__options{max-height:200px;overflow-y:auto}.select300-container--default .select300-results__option[role=group]{padding:0}.select300-container--default .select300-results__option[aria-disabled=true]{color:#999}.select300-container--default .select300-results__option[aria-selected=true]{background-color:#ddd}.select300-container--default .select300-results__option .select300-results__option{padding-left:1em}.select300-container--default .select300-results__option .select300-results__option .select300-results__group{padding-left:0}.select300-container--default .select300-results__option .select300-results__option .select300-results__option{margin-left:-1em;padding-left:2em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-2em;padding-left:3em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-3em;padding-left:4em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-4em;padding-left:5em}.select300-container--default .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option .select300-results__option{margin-left:-5em;padding-left:6em}.select300-container--default .select300-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select300-container--default .select300-results__group{cursor:default;display:block;padding:6px}.select300-container--classic .select300-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select300-container--classic .select300-selection--single:focus{border:1px solid #5897fb}.select300-container--classic .select300-selection--single .select300-selection__rendered{color:#444;line-height:28px}.select300-container--classic .select300-selection--single .select300-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select300-container--classic .select300-selection--single .select300-selection__placeholder{color:#999}.select300-container--classic .select300-selection--single .select300-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select300-container--classic .select300-selection--single .select300-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select300-container--classic[dir="rtl"] .select300-selection--single .select300-selection__clear{float:left}.select300-container--classic[dir="rtl"] .select300-selection--single .select300-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select300-container--classic.select300-container--open .select300-selection--single{border:1px solid #5897fb}.select300-container--classic.select300-container--open .select300-selection--single .select300-selection__arrow{background:transparent;border:none}.select300-container--classic.select300-container--open .select300-selection--single .select300-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select300-container--classic.select300-container--open.select300-container--above .select300-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select300-container--classic.select300-container--open.select300-container--below .select300-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select300-container--classic .select300-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select300-container--classic .select300-selection--multiple:focus{border:1px solid #5897fb}.select300-container--classic .select300-selection--multiple .select300-selection__rendered{list-style:none;margin:0;padding:0 5px}.select300-container--classic .select300-selection--multiple .select300-selection__clear{display:none}.select300-container--classic .select300-selection--multiple .select300-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select300-container--classic .select300-selection--multiple .select300-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select300-container--classic .select300-selection--multiple .select300-selection__choice__remove:hover{color:#555}.select300-container--classic[dir="rtl"] .select300-selection--multiple .select300-selection__choice{float:right;margin-left:5px;margin-right:auto}.select300-container--classic[dir="rtl"] .select300-selection--multiple .select300-selection__choice__remove{margin-left:2px;margin-right:auto}.select300-container--classic.select300-container--open .select300-selection--multiple{border:1px solid #5897fb}.select300-container--classic.select300-container--open.select300-container--above .select300-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select300-container--classic.select300-container--open.select300-container--below .select300-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select300-container--classic .select300-search--dropdown .select300-search__field{border:1px solid #aaa;outline:0}.select300-container--classic .select300-search--inline .select300-search__field{outline:0;box-shadow:none}.select300-container--classic .select300-dropdown{background-color:#fff;border:1px solid transparent}.select300-container--classic .select300-dropdown--above{border-bottom:none}.select300-container--classic .select300-dropdown--below{border-top:none}.select300-container--classic .select300-results>.select300-results__options{max-height:200px;overflow-y:auto}.select300-container--classic .select300-results__option[role=group]{padding:0}.select300-container--classic .select300-results__option[aria-disabled=true]{color:grey}.select300-container--classic .select300-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select300-container--classic .select300-results__group{cursor:default;display:block;padding:6px}.select300-container--classic.select300-container--open .select300-dropdown{border-color:#5897fb}
|
78 |
+
|
79 |
+
.select300-container {
|
80 |
+
display: block;
|
81 |
+
width: 100% !important;
|
82 |
+
}
|
83 |
+
|
84 |
+
.select300-container--default .select300-selection--multiple .select300-selection__choice {
|
85 |
+
border-radius: 20px;
|
86 |
+
background: #E2E4E7;
|
87 |
+
border: none;
|
88 |
+
color: #32373C;
|
89 |
+
padding-left: 8px;
|
90 |
+
font-family: Helvetica Neue, serif;
|
91 |
+
font-style: normal;
|
92 |
+
font-weight: normal;
|
93 |
+
font-size: 13px;
|
94 |
+
line-height: 24px;
|
95 |
+
}
|
96 |
+
|
97 |
+
.select300-container--default .select300-selection--multiple .select300-selection__choice__remove {
|
98 |
+
line-height: 1;
|
99 |
+
width: 16px;
|
100 |
+
height: 16px;
|
101 |
+
float: right;
|
102 |
+
display: block;
|
103 |
+
border-radius: 50%;
|
104 |
+
background-color: #555D66;
|
105 |
+
color: #E2E4E7;
|
106 |
+
text-align: center;
|
107 |
+
margin: 4px 0px 4px 8px;
|
108 |
+
font-size: 14px;
|
109 |
+
box-sizing: border-box;
|
110 |
+
padding-top: 0;
|
111 |
+
padding-left: 0;
|
112 |
+
}
|
113 |
+
|
114 |
+
.select300-container--default .select300-selection--multiple .select300-selection__choice__remove:hover {
|
115 |
+
background-color: #333;
|
116 |
+
color: #E2E4E7;
|
117 |
+
}
|
118 |
+
|
119 |
+
.exactmetrics-widget-theme-preview {
|
120 |
+
background: #F0F2F4;
|
121 |
+
border-radius: 5px;
|
122 |
+
padding: 8px 8px 8px 18px;
|
123 |
+
display: flex;
|
124 |
+
font-family: Helvetica Neue, serif;
|
125 |
+
font-style: normal;
|
126 |
+
font-weight: normal;
|
127 |
+
font-size: 14px;
|
128 |
+
line-height: 1;
|
129 |
+
color: #32373C;
|
130 |
+
align-items: center;
|
131 |
+
justify-content: space-between;
|
132 |
+
}
|
133 |
+
|
134 |
+
.exactmetrics-widget-theme-preview-icon,
|
135 |
+
.exactmetrics-products-theme-preview-icon {
|
136 |
+
width: 74px;
|
137 |
+
height: 46px;
|
138 |
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAxAAAAEqCAMAAACyWUYtAAABBVBMVEUAAADw6v6AUPeEU/bw6f7w6v7v5P/w6v/v6vzy6/9lKPWEU/jw6/7v6fzw6/5kKPVlJ/ZlKPZoKPOEU/fw6v7Rv/xkJ/VlKPbx6/9lKPaEU/eEU/fv6P3w6/7w6v7Rv/xkKPVkJvTPv//Pv/dwIPNgIO/v6f2EU/jw6v7Rv/xkJ/RmKPbv5//Sv/zQv/zw6v5lKPWEU/fRv/x5Qvbe0f1uNPbt5v50PfbTwvzTwfyATffs5P3ay/zi1/3NufuIWPdoLPWMXvjWxfyRZPjczv3YyPzNufy8ovt2P/bErfvk2v3g0/1xOfZsMvXo3v23mvt4Q/bKtfymgvmfePmujvp7RvaCUPf1uE5qAAAAL3RSTlMA3yDvr4AQz2Bf369vUK/vr2Agv+/vz7+PgO6+kO/ur29QICAQEI/vv76QjyC/v+TVgYYAAAyJSURBVHja7N3PTttAEMfxweZPi6FA0hJIVFVqizhVM1uFSyWDzAGSSyslff9nqZpDpCRu5djr9azn93mDkfYLsrye0Mrx2eEBd+7k8C158vV2JGpcXxFE5fwjK3HgJ4nBqahyOiCIxw0rckQeKOtB5PSOIBZHrMoNNXYl6twSROINK3NOTV2LOiOCSCh4mt70/pgaEoUI4qDuHwTzGYKAzrxjdQ4RBHTmhNU5oIZYIYI4/nCxQgjCBlGol4eHFSJAEAgCQSAIBYeHFSJAEAgCQSAIBYeHFSJAEAgCQSAIBYeHFSKIAyuEmaAqBGF0JiiHIIzOBOUQhNGZoByCMDoTlEMQRmeCcgjC6EwQCG95fJLAnuYIovquKdqWDFMXQpaQCbxpLh2YI4jKu6Z2ekhdIGMbRfCmmXTgAUFU3jVFWzIXzIQs4A3P0okpgqi6a4q2uHDGZAFveJROvLQcRL4sXEiLnLf52TXVaRCOLLAQRF64wIrcdxCygiB2IYi9g1i44JYIIlIWgnDhFQgiUgiiHQiigsHoQvZzOWjzDUyWIIg1BBE8iMGF7O1i0OYbmHGCINYQROggLqWGUatvYCYIYg1BhA5C6rhodfIxglhDEFEEIe1OjiDWEASC2AliKp14RhB1g0jdfyCIpkHwg3RgxgiibhBDF0xmMYheXv92lcQZRLjr32liMQieh/9A6IURRO0gKMlcCOkkIZNBaOA7iMJVEWkQEZNaNp+eEESNIJYuuAWCaDuIoWtBZiKIPl//jpnU0ubTU5qYCILzhQupWOaMINoKor2np3SS9PNzS1YIQXgLohz2MtmaCUEgCMyEIBAEgkAQqoIIsLnvxyuCqB9EiM19WUKlDAYxlxB+IwjdVzfG5UUYDGImQfxEEJ6CyFwrJlTGXhDPEsYrgtD9PcSYSpkL4lF8URWEz819i9xCEI5KqQqiydNTllgOwu/VjSJHEBqCaPb0dJ8YDmLhvFoiCA1BZK6RoeEgnF8FgtAQhGvmHkF4gyB6EIRDEAgCQSAIBIEgEASCQBAIAkEgCARhJoiR/IUgAgcxlTDmCGJPt7Lyr819BoNIAwQRbHPfFEHs6e5UVgJt7stol7IgGk6eGb7+3Ycgwv5wexrB9e8kbWPCLjb3zX4xgqjh6lrCbO5LJ1F8INRg8nSYWLoqzVuKfgTRO1IDvqnWt7lvgSAQRHUKg+jD9e8+QhA92NxXLHNGEAhiDwqDUIAAQSAIBIEgFBweVogAQSAIBIEgFBweVojAdxBfvn347tenz/08PKwQwR/27Ca1cSAIwGgJLNkG2wnGJllkMCSbBMIU6P6Hm8X8wGxCEkuoJL93g4L6aKl74CBezv3gzs+LXJ4sKBg4iEs/grdFLk8WFAwcRD+G8yKXJwsK5hBEv8jlyYICQQhCEB+5uyqIcz+GaLKctSBuw8N3eriPP372I7jEIctZCeI2HL9xRNwdR7523WU5W0HciOP9V3N4OMY/L5ehc3h7juhOWUzj9Z0J7bOYbVzrNctZB3PxlKW0cbU2y9kGs1Fqf57iel25q7MmmJFNmQU67WMI72UG+q15D2Zlc1jn5JrDrhtsoALz/PXadgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwA3rdqsmJ7debQOmt/+RRTSSYHKPWUgbMKk2S3kMmNAmi9kHTKfA3/T/Tl3AZy3+gMjcBUzlkOWsAj5v4V9MmU3AVLKg4Bd7d9DaNhCEYdi3QmhpcgnkUhJoTznMyLUiRzFY4CY4YAVd7P//UypoVDzbdFf2yuvR7vechcAoL7KtmRh6QhAAexAEwB4EAbAHQQDsQRAAexAEwCmRabbMOaTVDEGAHmSY5RxYPkMQoAYZVhzcEkGAGmTg8HIEAWooCIIRBHbf1SABQWiG3fcPIIhkYff9IwgiVdh9/xCCSJS61cZId99JQBBqKfg0LX2Lc/edBAShlbobxFC7799vLy/47K4vrxDEqMS6+373lZW4uEIQI/KJ1Bli9/2eFblBEONBCk283bAq9whiNEihia8rVuYOQYwFKTTxpeDTtPT1B4IYCVIouhsE8y2CGAlSaOLpktW5jDeIyCZDSaGJp2tW5yLaIGKbDCWFJp5YoViDiG4ylCT77vtqRk4IIqUg4psMJcG1+567i0AQCQWhbvDnS+jd9yW5IIiEglDwadr8VaTAQ5g5uSCIdIJQd4Mg+hw4CCYXBJFOEDFOhpKAIDoIItHJUBIQRAdBJPqdPQkIooMgEEQLQXQQBIJoIYgOgkAQrXSCqH+W2SDKpkYQiiCIY4KottmAmgpBqIEgjgiiKrNBlRWC0AJBHBFEkw1siyBaUfwqEhlytokjiDobXM1WiQQRw68ikWHJVityUx9Ekw2uYatEgojhV5FISGP8u8wGV7JVIkFwePnp3wb+P/N8GceCUHYCbIUgOqN7TRogiD4U/vGw2+hekwaBg9iuN5uiKREEgkAQbQ41/7EpEQSCSD6Igv+qSgSBIEihgEEUvKcqEQSCUChcEA0L1Q5BeD/VtRvda9IgXBAVSwWC8HuqG9wKQQwYxJYN1Q5BYHRjXxTzWeyQdTZs2iIIz6e6IeXLGSHyAYOo2VQgiMTfXpAQx3wWWyEIBKH7m7N8LEGUmwZBIIh/qL9ObGX9DNHYeqiYCwSBIEzqrxM7ZJ01m0prD60CQSAIg/rrxA5ZZ1exVDt6aBUIAkFI6q8TO4jJDaF09dAqjgoCT3V7QRBnDcK8RRS2HuxHsQOe6vaCIFrnC0L+odt7cBzHDlE+8CHT0+Jx6uPXkzyX+/iz/9eNUzjn+He54XfV2taDUBweRBJPdZ8ep57mT/Jc7uMxnzVEEDKJmrmqi521B1cR7JDE24vF1NviwHMtMLoRbKda9iAVCKJFhqm/+YHnmmM+K1wQsgepQBCWIDwcei58URAwCNmDVCAIBNGHguvEDsf2IBUIggzzAYOYI4jTBbF+eaOQXtdpBvE89bY48FwLEhBEnyDWbxTY2zrJIB68bxGPD+JcfY4XEESfIF4puJckg6CHhV8Ozw/iXH2OlxBEnyAovDc2RLmrSwrhNakMglhIZXRDAbymkQYRw64uKYT5rJEGweHlJCCIVOazWEAQ77APkep8FoL43c7drjQOhFEAHqF+4kcFEQQRhV1/+OedzkLrurRgqS22xRDo/V/LrhC6k2yWppmanLw5zx3M0IMyPacMBNK377X3sxgIBgIpELXXUWzGh1SNgagJA1EkEFOp3HtbA9FfjJ17m/ySerCf1djqht1WIwIxT95RnodSC/azipX73qVKH6NsHtryqxtDtzaXOrCfFfozNEEG/NUNT/qd/bkvJeAFQkM/qxGB0FjdmDjPQsrACwSAVgRCw1ZXMsbOM5Yyav/wCKB2BALA1z5RytYQz4SAgcgHd9GSwkAk4M7EQOSr9l+mN9ka4pkQMBD54C5aMhbOM5GtIZ4JQXWBePkR5IWB8KTf2X9qeXYFsPNADKLYhYhee2uvs5HbZLVsZyBk7taGUgLimQDsOhCD2AWavq7zMHIFxMt2BkKGz8nfh7mUgnim5vezbMbKBZv1EpErJGppIKQ/GTs3XvSlJMAzNb+fZTNcuGkv4YqJbYbKra4AYj+rkkC4LQPhbIbKra4AYj+roYHQsNUVQOxnbQ5E7ML1ElNXjM1QudUVQOxnbQ5E5IJFvcTMFbKyGSqniQKIdZQqnl1Hf59dp66AeMlAlAHw4ZEUnYGwg5ULMZr5X8xFbpM4WtoslVtdAcR+1r8sIJVb3T2Bc8h+VkMDoWGrey5wOuxnNTQQGra6pwLnmP2spgYCgAl0cCVg9gz7WQxEaSbUmYA5NuxnMRClmWC3AmXfGL6cMRClmXD7AuTWMBB5Tiyca5UX/ekI5u316swwELm6Fk5X5UUnkTg/lNrtnZ8eGAYi372Fc6nyojUSQCbQ9wsL5kTnRWskgEyoBwvmUudWVyMBZII9WSg3Sre6GsG8Efj9rHA3FsiT1q2uRhr7WZ8uYd5eLx7UbnU10tjPSiLRvba1O+nef9O71dVIYz8LkqTo2OqqpLCfBUlSdEwTddLXz4IkKQwEMKh+1qNRSlJ0bHW1wuln3Z0ZrSRFx1ZXL139LEiSomOrS8StLtEf3OoSebjVJTKGLUqiTwwEkYeBIPIwEEQeBoLIw0AQeRgIolzc6hLtXkfgdAzRdrjVJfoSB3cCRulWlxqCW10i36NA0brVpcbgVpeIW12i/zrqIGx1O5q3utQIvwFN0uiXuNQl8wAAAABJRU5ErkJggg==);
|
139 |
+
background-repeat: no-repeat;
|
140 |
+
background-position: 0 0;
|
141 |
+
background-size: 392px;
|
142 |
+
display: inline-block;
|
143 |
+
}
|
144 |
+
|
145 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-beta {
|
146 |
+
background-position-x: -212px;
|
147 |
+
}
|
148 |
+
|
149 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-charlie {
|
150 |
+
background-position-x: -106px;
|
151 |
+
}
|
152 |
+
|
153 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-delta {
|
154 |
+
height: 43px;
|
155 |
+
background-position: -318px 0;
|
156 |
+
}
|
157 |
+
|
158 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-echo {
|
159 |
+
height: 76px;
|
160 |
+
background-position: 0 -73px;
|
161 |
+
}
|
162 |
+
|
163 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-foxtrot {
|
164 |
+
background-position: -106px -90px;
|
165 |
+
height: 41px;
|
166 |
+
}
|
167 |
+
|
168 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-golf {
|
169 |
+
background-position: -212px -83px;
|
170 |
+
height: 56px;
|
171 |
+
}
|
172 |
+
|
173 |
+
.exactmetrics-widget-theme-preview-icon.exactmetrics-widget-theme-preview-icon-hotel {
|
174 |
+
height: 50px;
|
175 |
+
background-position: -318px -86px;
|
176 |
+
}
|
177 |
+
|
178 |
+
.exactmetrics-products-theme-preview-icon {
|
179 |
+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlAAAACcCAMAAACHiWWRAAAA3lBMVEUAAABlKPX///9oKPNlJ/ZkKPVkKfRlKPZlKPVlKPbRv/zw6v7Pv/vw6/7w6v7w6v7w6/7v6vzy6//w5f/w6v5lJ/Xw6f5lKPXv6fxlH/Pw6f7w6v7Rv/zRv/xkKPVmJ/VlJvZjJvLw6/7w6v/w6v9jJ/NmKfbv6PxlKPXw6v7Rv/yEU/f///95QvZmKfXs5f7Twvx/TPd0PfZuNPbZyv1pLfXbzf11PvZyOvbf0v3e0P2RZPiIWPfNuvzKtftsMvX18v7+/v+NYfh7Rva2mfq5nfuCUPe+pPuvkPqvkPnAI7BMAAAAKHRSTlMA/gEgr+/uv99g798gr5CAb2BfEO/PsIBQEN/Pv69wj1BQ78/OkI5P5JBZSwAAB1NJREFUeNrs3EtqAkEYReFqYhJF8o4vBPMYhFuIgjhTwUH2v6eM09GyUOmckvut4MJ/aHVgByvYVVso7atgJYP1JLVHwcrVEc4gWLl6wrkNVi7xVMHKJR4HVTLxOKiSicdBlUw8Dqpk4nFQJROPgyqZeBxUycQDDurlsd+N/27cfw5Y4uEGNfyMEF1sUuLBBnUfQR4Ck3ioQT1ElPuAJB5oUE8RZhiIxAMNCvBt/LfXlwAkHmZQuAdUjI8BSDzMoO4iTj8AiYcZ1DjidAOQeJhBRaAAJB4H5aAcVA4HlcVB5XJQWRxULgeVxUHlclBZHFQDEkGNJi3Av797rY6DOi2o1WapJq1XO4N6vxFEu+OgTghqtVTDlqsdQb2Joxo4qOODWqtxm79BDYTy5aCODkrNW8Ya3KtOqg8HVVBQijW8dzFdj8TjoPaJNbQHlFRNxOOg9ok1LeEAJzmovWIN8OVeuA9hOaj9CBsOqMTjoHZzUEeqiD89EcckbEhyULkYxyRsSHJQuRjHJGxIclC5GMckbEhyULkYxyRsSHJQuRjHJGxIclC5GMckbEhyULkYxyRsSKIGRUQ4JmFDkoO6/KC2s8X0LBazrQ5xUJce1Px7ekazudIc1IUHNV9Mz2oxV5KDuvCgfti5tyVFYSgKw1YB8iqrxViFaAXPjrb2zPu/0DCtJbZj04GEmMD67+HquwnZG5EY7ojKCKrboHaJ8XaoiqC6DUokxhOoiqC6DSpNjJeiKoLqNqikhVAVQREUQalFUPgP1FHmeS5SgnIi70Edd7iUpwTlQL6DmuLWPCWo1+c5qCnKClEE9fL8BiXwpfmZoGrWT1D5+3ak1unQK1BBPES9wmBwS/1p9bd7ASrfjpTbHHoEKmgAIrqJUni6wdt9APV7VKOPHoEK0aB4cC1EC8U+gBrVadMjUGhS1OqPjaPOgRoR1A+1CcqNeW5boNJcEBRBAVszoNI5IAmKoPBex9OpyhMgCYqgtD8blJ4ASVC9B4X8jyqnj588AZKgeg/qoZLBeY6y0kqVJ0AS1GcRzOc7qHsoqp4AWR/U5M3BNEHFaKHQc1BJmuPaRNUTIAmqKIhgvKEXVy+PPWjJd8BkNz0rewIkQRUFIcw2jP24HH4sqUjJEyAJ6lI/x1ce0vcESIL6jKCKDHgCJEH9i6CKTHgCJEEV9ROUmO3HOm0EniQIajDoJSixH2u2fy6KoAa9BLUZazfDs44E1TqoDJZSBzUZ67fHs6YE1TqoNay3sgDqF0HdMrL1EgaKoBYZLJctCMo6KP2tlyhQAlWIWsFm2XrxRlAvARVCq/gbUA5GUFZAQa+IoAjKJCgQlFFQy3UGm62WBGUK1N5BUEv7h5clQZkBhZk+qA0Ao6BWsN6aoBSzc/WiB8qBG4WMoAyBgtjocZoJAN6DAkEp1nx8ZQrlCOqSqa0XRVBOnF5QRlB3ubX1EqqAcuP0glsEdZ9TWy/DQAWUG6cXXCOorzm09TKMA3fnoTKCUsvL8RW8IB9BuTA3RlAdAuXC3BhBGQeVCq3SpqDcmBsjqKc1+E/56ZCYqTEoJ+bG/rJzRy0Nw0AAxzOtYy19HWPQTn0Q7g5mMgjBFzfQqd//GwmzL7sVasPVXW1+r4V7GH/KGpKkoFrFXDj2+nb1oBRIQbWKuqf8KwU1kqA0fL0A03obuawdpKAmc+oFqIVwUFuYYFBlVZCsuhzDqZe/COoA0wuqLEhcUeI5FV8vwOzpkvgLanpB1TSAChUC5kgXPmT/QT0DwOSCoiEUqFD3ssH+U7Kn91NPKSgRqBAw/J7y/fEFDtud0Ntpe4BGr6Csd9RfsNhIQQ1Hw1oY9AzKOoriBIuK3HNpGgXFSUFF6AwqUCSPYuL2XGamUdEAalQI9LkIimI5FBO153J+O/CygUKgj1xQhGJ677lkOy3LWjqnqhzlqRdZYw5KIeSsdyQpWD6bPx9lUI56m2ZQ1pEwZ/ls/nyMQXmKFPDHVIIKJM53zPbILECdJZ5RsmygETIkz3XMdshkoE6GnA3Un/MWGymoeF2zkdmANrMcFTIa4RkdQa3vQJnFDSpkNELGkbyu2ciYR9BllqegYoPyJC50zA7IGPMEqqxMCmrMywbGmBUocm9SUL+GnA2yOXnLZ/PnrT9UrmbtYP5gUlBtxnPhmDnJsyVc3SLbrE0K6l8EpUoKKgX13a7dpSAIRVEU3vga9qeE2GNBHJ98kOY/tAZgN66CtLutbwiHhaDbTYNKbZ75/2SWeSeCWhdU+uUld1wp9E4EtTao55A0RYZC70RQa4Ma0sbIUOidCGqDoIbIUOidpF3YuckPQeWqw85FfmZBjQT13jHsnOVnFtT0abvMUGxQTRtmehnis0G2Lsw4PqBmQSU3z3H68w+b0j6sHOSI6WWBQxjZyxJBLXHqw0TbyRNBLXOqr/F1u/rYyBRBgaDgi6BAUPBVGW6ed+FnVWyeEJsnbLF5QmLzhK2KzRMSmyd8GW2eD6EEbJ4o2AuunoM0UoU65AAAAABJRU5ErkJggg==');
|
180 |
+
width: 74px;
|
181 |
+
height: 39px;
|
182 |
+
background-size: 188px;
|
183 |
+
}
|
184 |
+
|
185 |
+
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-alpha {
|
186 |
+
background-position: 0 0;
|
187 |
+
}
|
188 |
+
|
189 |
+
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-beta {
|
190 |
+
background-position: -114px 0;
|
191 |
+
height: 65px;
|
192 |
+
}
|
193 |
+
|
194 |
+
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-charlie {
|
195 |
+
background-position: 0 -102px;
|
196 |
+
height: 50px;
|
197 |
+
}
|
198 |
+
|
199 |
+
.exactmetrics-products-theme-preview-icon.exactmetrics-products-theme-preview-icon-delta {
|
200 |
+
background-position: -114px -102px;
|
201 |
+
height: 78px;
|
202 |
+
}
|
203 |
+
|
204 |
+
.exactmetrics-pro-pill {
|
205 |
+
font-style: normal;
|
206 |
+
font-weight: bold;
|
207 |
+
font-size: 11px;
|
208 |
+
background: #1EC185;
|
209 |
+
border-radius: 5px;
|
210 |
+
color: #fff;
|
211 |
+
padding: 3px 8px;
|
212 |
+
margin-left: 8px;
|
213 |
+
}
|
214 |
+
|
215 |
+
.select300-container--disabled {
|
216 |
+
margin-top: 10px;
|
217 |
+
opacity: 0.6;
|
218 |
+
}
|
assets/images/plugin-pushengage.svg
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<svg width="470" height="74" viewBox="0 0 470 74" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2 |
-
<path d="M73.1 30.9C73 40.3 70.2 47.8 64.6 54.2C63.6 55.4 62.4 56.5 61.2 57.5C60.1 58.5 58.5 58.5 57.6 57.5C56.7 56.4 56.9 54.9 58.1 53.9C60.6 51.8 62.6 49.4 64.2 46.6C66.6 42.5 68 38.1 68.2 33.3C68.6 25 66 17.9 60.5 11.8C59.7 11 58.8 10.2 58 9.39998C56.9 8.39998 56.7 6.79998 57.6 5.79998C58.5 4.69998 60 4.69998 61.2 5.79998C67.6 11.3 71.4 18.3 72.8 26.6C73 28.3 73 30 73.1 30.9Z" fill="#3B43FF"/>
|
3 |
-
<path d="M5 31.7C5.2 21.3 9.1 12.6 17 5.69998C18.1 4.69998 19.7 4.79998 20.5 5.79998C21.4 6.79998 21.2 8.39998 20.1 9.29998C14.7 14 11.3 19.8 10.2 26.9C8.7 36.2 11.2 44.4 17.5 51.4C18.3 52.3 19.3 53.2 20.2 54C21.3 55 21.4 56.5 20.5 57.5C19.6 58.5 18.1 58.5 17 57.6C10 51.6 6 43.9 5.2 34.7C5.2 34.2 5.1 33.7 5.1 33.2C5 32.7 5 32.2 5 31.7Z" fill="#3B43FF"/>
|
4 |
-
<path d="M14.7 31.6C14.9 24.2 17.6 18 23.3 13.1C24.5 12.1 25.8 12.2 26.8 13.3C27.7 14.3 27.6 15.6 26.4 16.7C23.7 19.2 21.5 22.1 20.4 25.7C18.3 33 19.8 39.5 25 45.1C25.5 45.7 26.1 46.2 26.6 46.8C27.5 47.7 27.6 49.1 26.8 50C26 51 24.4 51.2 23.5 50.3C22 48.9 20.6 47.5 19.3 45.9C16.6 42.3 15.1 38.2 14.8 33.6C14.8 33.3 14.7 33 14.7 32.6C14.7 32.3 14.7 32 14.7 31.6Z" fill="#3B43FF"/>
|
5 |
-
<path d="M63.4 31.7C63.2 38.9 60.5 45 55.1 49.9C54.3 50.7 53.3 51.1 52.2 50.7C50.6 50 50.2 48.2 51.4 46.8C52.8 45.2 54.4 43.7 55.6 41.9C60.4 34.5 59.3 24.4 53 18.1C52.5 17.6 52 17.1 51.5 16.6C50.6 15.7 50.5 14.3 51.3 13.4C52.2 12.4 53.6 12.2 54.7 13C56.7 14.6 58.4 16.5 59.7 18.7C61.8 22.1 63.1 25.8 63.3 29.8C63.3 30.4 63.3 31 63.4 31.7Z" fill="#3B43FF"/>
|
6 |
-
<path d="M53.5 31.1C53.5 36.1 51.8 39.6 48.6 42.6C47.5 43.7 45.9 43.7 45 42.6C44.1 41.6 44.1 40.1 45.3 39.1C47.3 37.2 48.6 34.9 48.7 32.1C48.8 29.4 48 27.1 46.2 25.1C45.9 24.7 45.5 24.4 45.2 24.1C44.2 23.1 44.1 21.7 45 20.7C45.9 19.7 47.4 19.6 48.5 20.6C50.2 22.1 51.5 23.9 52.4 26C53.2 27.8 53.6 29.7 53.5 31.1Z" fill="#3B43FF"/>
|
7 |
-
<path d="M30.9 19.9C32.3 19.9 33 20.4 33.5 21.4C34 22.4 33.7 23.4 32.9 24.1C31.6 25.4 30.5 26.7 29.9 28.5C28.7 32.3 29.5 35.6 32.1 38.5C32.3 38.8 32.6 39 32.9 39.3C33.9 40.4 34 41.8 33 42.8C32.1 43.7 30.6 43.8 29.6 42.9C27.1 40.7 25.4 38.1 24.9 34.8C23.9 29.4 25.4 24.7 29.4 21C29.9 20.3 30.6 20.1 30.9 19.9Z" fill="#3B43FF"/>
|
8 |
-
<path d="M38.9 36.4C36.2 36.4 34.1 34.3 34.1 31.6C34.1 28.9 36.3 26.8 39 26.8C41.7 26.8 43.8 28.9 43.8 31.6C43.8 34.4 41.7 36.4 38.9 36.4Z" fill="#3B43FF"/>
|
9 |
-
<path d="M89.752 56H100.624V38.648C101.632 38.792 102.928 38.864 104.368 38.864C110.848 38.864 116.392 37.28 120.136 33.752C123.016 31.016 124.6 26.984 124.6 22.232C124.6 17.48 122.512 13.448 119.416 11C116.176 8.40801 111.352 7.11201 104.584 7.11201C97.888 7.11201 93.136 7.54401 89.752 8.12001V56ZM100.624 15.824C101.416 15.608 102.928 15.392 105.16 15.392C110.632 15.392 113.728 18.056 113.728 22.52C113.728 27.488 110.128 30.44 104.296 30.44C102.712 30.44 101.56 30.368 100.624 30.152V15.824Z" fill="#191A35"/>
|
10 |
-
<path d="M162.277 20.792H151.261V41.744C151.261 42.608 151.189 43.472 150.901 44.12C150.181 45.848 148.453 47.936 145.429 47.936C141.613 47.936 139.957 44.84 139.957 39.728V20.792H128.941V41.456C128.941 52.328 134.197 56.792 141.325 56.792C147.661 56.792 150.973 53.192 152.341 51.032H152.557L153.061 56H162.565C162.421 53.048 162.277 49.304 162.277 44.696V20.792Z" fill="#191A35"/>
|
11 |
-
<path d="M167.605 54.272C170.269 55.712 174.373 56.72 178.981 56.72C189.061 56.72 194.245 51.896 194.245 45.344C194.173 40.16 191.365 36.776 184.669 34.472C180.349 32.96 178.981 32.096 178.981 30.44C178.981 28.64 180.493 27.56 183.157 27.56C186.181 27.56 189.205 28.712 190.789 29.576L192.733 22.016C190.573 20.936 186.901 20 182.797 20C174.085 20 168.469 24.968 168.469 31.52C168.397 35.696 171.205 39.656 178.477 42.104C182.581 43.472 183.661 44.336 183.661 46.136C183.661 47.936 182.293 49.088 178.981 49.088C175.741 49.088 171.565 47.648 169.549 46.424L167.605 54.272Z" fill="#191A35"/>
|
12 |
-
<path d="M199.4 56H210.344V35.12C210.344 34.328 210.416 33.392 210.704 32.672C211.496 30.728 213.296 28.856 216.176 28.856C220.28 28.856 221.864 32.024 221.864 36.632V56H232.808V35.408C232.808 24.824 227.48 20 220.496 20C218.48 20 216.392 20.504 214.808 21.368C213.08 22.304 211.64 23.456 210.488 24.968H210.344V4.88H199.4V56Z" fill="#191A35"/>
|
13 |
-
<path d="M269.38 26.552H251.524V16.472H270.46V7.47201H240.508V56H271.468V47H251.524V35.48H269.38V26.552Z" fill="#191A35"/>
|
14 |
-
<path d="M277.169 56H288.113V35.696C288.113 34.688 288.257 33.608 288.545 32.96C289.265 30.944 291.065 28.856 294.089 28.856C298.049 28.856 299.633 31.952 299.633 36.488V56H310.577V35.12C310.577 24.752 305.177 20 297.977 20C292.145 20 288.545 23.384 287.105 25.616H286.889L286.385 20.792H276.881C277.025 23.888 277.169 27.632 277.169 32.024V56Z" fill="#191A35"/>
|
15 |
-
<path d="M342.036 20.792L341.676 24.968H341.532C339.732 22.088 336.708 20 331.884 20C323.244 20 315.9 27.2 315.9 38.504C315.9 48.656 322.092 55.712 330.804 55.712C334.836 55.712 338.22 54.056 340.308 51.104H340.452V53.408C340.452 59.888 336.492 62.696 331.308 62.696C327.204 62.696 323.316 61.328 321.084 60.032L318.924 68.312C322.092 70.112 326.988 71.048 331.596 71.048C336.78 71.048 342.036 70.04 345.924 66.728C349.884 63.2 351.252 57.656 351.252 50.888V31.232C351.252 25.976 351.396 23.024 351.54 20.792H342.036ZM340.308 40.304C340.308 41.24 340.236 42.392 339.948 43.184C339.228 45.776 336.996 47.648 334.188 47.648C329.58 47.648 326.988 43.544 326.988 38.288C326.988 31.88 330.228 28.28 334.188 28.28C337.212 28.28 339.3 30.224 340.092 33.104C340.236 33.68 340.308 34.4 340.308 35.12V40.304Z" fill="#191A35"/>
|
16 |
-
<path d="M388.473 56C388.113 54.056 387.969 50.816 387.969 47.432V35.192C387.969 26.912 384.225 20 372.489 20C366.081 20 361.257 21.728 358.809 23.096L360.825 30.152C363.129 28.712 366.945 27.488 370.545 27.488C375.945 27.488 376.953 30.152 376.953 32.024V32.528C364.497 32.456 356.289 36.848 356.289 45.992C356.289 51.608 360.537 56.792 367.665 56.792C371.841 56.792 375.441 55.28 377.745 52.472H377.961L378.609 56H388.473ZM377.313 43.184C377.313 43.832 377.241 44.48 377.097 45.056C376.377 47.288 374.145 49.088 371.409 49.088C368.961 49.088 367.089 47.72 367.089 44.912C367.089 40.664 371.553 39.296 377.313 39.368V43.184Z" fill="#191A35"/>
|
17 |
-
<path d="M419.312 20.792L418.952 24.968H418.808C417.008 22.088 413.984 20 409.16 20C400.52 20 393.176 27.2 393.176 38.504C393.176 48.656 399.368 55.712 408.08 55.712C412.112 55.712 415.496 54.056 417.584 51.104H417.728V53.408C417.728 59.888 413.768 62.696 408.584 62.696C404.48 62.696 400.592 61.328 398.36 60.032L396.2 68.312C399.368 70.112 404.264 71.048 408.872 71.048C414.056 71.048 419.312 70.04 423.2 66.728C427.16 63.2 428.528 57.656 428.528 50.888V31.232C428.528 25.976 428.672 23.024 428.816 20.792H419.312ZM417.584 40.304C417.584 41.24 417.512 42.392 417.224 43.184C416.504 45.776 414.272 47.648 411.464 47.648C406.856 47.648 404.264 43.544 404.264 38.288C404.264 31.88 407.504 28.28 411.464 28.28C414.488 28.28 416.576 30.224 417.368 33.104C417.512 33.68 417.584 34.4 417.584 35.12V40.304Z" fill="#191A35"/>
|
18 |
-
<path d="M466.973 41.888C467.117 41.096 467.333 39.44 467.333 37.568C467.333 28.856 463.013 20 451.637 20C439.397 20 433.853 29.864 433.853 38.792C433.853 49.808 440.693 56.72 452.645 56.72C457.397 56.72 461.789 56 465.389 54.56L463.949 47.144C460.997 48.08 457.973 48.584 454.229 48.584C449.117 48.584 444.653 46.424 444.293 41.888H466.973ZM444.221 34.4C444.509 31.448 446.381 27.272 450.989 27.272C456.029 27.272 457.181 31.736 457.181 34.4H444.221Z" fill="#191A35"/>
|
19 |
-
</svg>
|
1 |
+
<svg width="470" height="74" viewBox="0 0 470 74" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2 |
+
<path d="M73.1 30.9C73 40.3 70.2 47.8 64.6 54.2C63.6 55.4 62.4 56.5 61.2 57.5C60.1 58.5 58.5 58.5 57.6 57.5C56.7 56.4 56.9 54.9 58.1 53.9C60.6 51.8 62.6 49.4 64.2 46.6C66.6 42.5 68 38.1 68.2 33.3C68.6 25 66 17.9 60.5 11.8C59.7 11 58.8 10.2 58 9.39998C56.9 8.39998 56.7 6.79998 57.6 5.79998C58.5 4.69998 60 4.69998 61.2 5.79998C67.6 11.3 71.4 18.3 72.8 26.6C73 28.3 73 30 73.1 30.9Z" fill="#3B43FF"/>
|
3 |
+
<path d="M5 31.7C5.2 21.3 9.1 12.6 17 5.69998C18.1 4.69998 19.7 4.79998 20.5 5.79998C21.4 6.79998 21.2 8.39998 20.1 9.29998C14.7 14 11.3 19.8 10.2 26.9C8.7 36.2 11.2 44.4 17.5 51.4C18.3 52.3 19.3 53.2 20.2 54C21.3 55 21.4 56.5 20.5 57.5C19.6 58.5 18.1 58.5 17 57.6C10 51.6 6 43.9 5.2 34.7C5.2 34.2 5.1 33.7 5.1 33.2C5 32.7 5 32.2 5 31.7Z" fill="#3B43FF"/>
|
4 |
+
<path d="M14.7 31.6C14.9 24.2 17.6 18 23.3 13.1C24.5 12.1 25.8 12.2 26.8 13.3C27.7 14.3 27.6 15.6 26.4 16.7C23.7 19.2 21.5 22.1 20.4 25.7C18.3 33 19.8 39.5 25 45.1C25.5 45.7 26.1 46.2 26.6 46.8C27.5 47.7 27.6 49.1 26.8 50C26 51 24.4 51.2 23.5 50.3C22 48.9 20.6 47.5 19.3 45.9C16.6 42.3 15.1 38.2 14.8 33.6C14.8 33.3 14.7 33 14.7 32.6C14.7 32.3 14.7 32 14.7 31.6Z" fill="#3B43FF"/>
|
5 |
+
<path d="M63.4 31.7C63.2 38.9 60.5 45 55.1 49.9C54.3 50.7 53.3 51.1 52.2 50.7C50.6 50 50.2 48.2 51.4 46.8C52.8 45.2 54.4 43.7 55.6 41.9C60.4 34.5 59.3 24.4 53 18.1C52.5 17.6 52 17.1 51.5 16.6C50.6 15.7 50.5 14.3 51.3 13.4C52.2 12.4 53.6 12.2 54.7 13C56.7 14.6 58.4 16.5 59.7 18.7C61.8 22.1 63.1 25.8 63.3 29.8C63.3 30.4 63.3 31 63.4 31.7Z" fill="#3B43FF"/>
|
6 |
+
<path d="M53.5 31.1C53.5 36.1 51.8 39.6 48.6 42.6C47.5 43.7 45.9 43.7 45 42.6C44.1 41.6 44.1 40.1 45.3 39.1C47.3 37.2 48.6 34.9 48.7 32.1C48.8 29.4 48 27.1 46.2 25.1C45.9 24.7 45.5 24.4 45.2 24.1C44.2 23.1 44.1 21.7 45 20.7C45.9 19.7 47.4 19.6 48.5 20.6C50.2 22.1 51.5 23.9 52.4 26C53.2 27.8 53.6 29.7 53.5 31.1Z" fill="#3B43FF"/>
|
7 |
+
<path d="M30.9 19.9C32.3 19.9 33 20.4 33.5 21.4C34 22.4 33.7 23.4 32.9 24.1C31.6 25.4 30.5 26.7 29.9 28.5C28.7 32.3 29.5 35.6 32.1 38.5C32.3 38.8 32.6 39 32.9 39.3C33.9 40.4 34 41.8 33 42.8C32.1 43.7 30.6 43.8 29.6 42.9C27.1 40.7 25.4 38.1 24.9 34.8C23.9 29.4 25.4 24.7 29.4 21C29.9 20.3 30.6 20.1 30.9 19.9Z" fill="#3B43FF"/>
|
8 |
+
<path d="M38.9 36.4C36.2 36.4 34.1 34.3 34.1 31.6C34.1 28.9 36.3 26.8 39 26.8C41.7 26.8 43.8 28.9 43.8 31.6C43.8 34.4 41.7 36.4 38.9 36.4Z" fill="#3B43FF"/>
|
9 |
+
<path d="M89.752 56H100.624V38.648C101.632 38.792 102.928 38.864 104.368 38.864C110.848 38.864 116.392 37.28 120.136 33.752C123.016 31.016 124.6 26.984 124.6 22.232C124.6 17.48 122.512 13.448 119.416 11C116.176 8.40801 111.352 7.11201 104.584 7.11201C97.888 7.11201 93.136 7.54401 89.752 8.12001V56ZM100.624 15.824C101.416 15.608 102.928 15.392 105.16 15.392C110.632 15.392 113.728 18.056 113.728 22.52C113.728 27.488 110.128 30.44 104.296 30.44C102.712 30.44 101.56 30.368 100.624 30.152V15.824Z" fill="#191A35"/>
|
10 |
+
<path d="M162.277 20.792H151.261V41.744C151.261 42.608 151.189 43.472 150.901 44.12C150.181 45.848 148.453 47.936 145.429 47.936C141.613 47.936 139.957 44.84 139.957 39.728V20.792H128.941V41.456C128.941 52.328 134.197 56.792 141.325 56.792C147.661 56.792 150.973 53.192 152.341 51.032H152.557L153.061 56H162.565C162.421 53.048 162.277 49.304 162.277 44.696V20.792Z" fill="#191A35"/>
|
11 |
+
<path d="M167.605 54.272C170.269 55.712 174.373 56.72 178.981 56.72C189.061 56.72 194.245 51.896 194.245 45.344C194.173 40.16 191.365 36.776 184.669 34.472C180.349 32.96 178.981 32.096 178.981 30.44C178.981 28.64 180.493 27.56 183.157 27.56C186.181 27.56 189.205 28.712 190.789 29.576L192.733 22.016C190.573 20.936 186.901 20 182.797 20C174.085 20 168.469 24.968 168.469 31.52C168.397 35.696 171.205 39.656 178.477 42.104C182.581 43.472 183.661 44.336 183.661 46.136C183.661 47.936 182.293 49.088 178.981 49.088C175.741 49.088 171.565 47.648 169.549 46.424L167.605 54.272Z" fill="#191A35"/>
|
12 |
+
<path d="M199.4 56H210.344V35.12C210.344 34.328 210.416 33.392 210.704 32.672C211.496 30.728 213.296 28.856 216.176 28.856C220.28 28.856 221.864 32.024 221.864 36.632V56H232.808V35.408C232.808 24.824 227.48 20 220.496 20C218.48 20 216.392 20.504 214.808 21.368C213.08 22.304 211.64 23.456 210.488 24.968H210.344V4.88H199.4V56Z" fill="#191A35"/>
|
13 |
+
<path d="M269.38 26.552H251.524V16.472H270.46V7.47201H240.508V56H271.468V47H251.524V35.48H269.38V26.552Z" fill="#191A35"/>
|
14 |
+
<path d="M277.169 56H288.113V35.696C288.113 34.688 288.257 33.608 288.545 32.96C289.265 30.944 291.065 28.856 294.089 28.856C298.049 28.856 299.633 31.952 299.633 36.488V56H310.577V35.12C310.577 24.752 305.177 20 297.977 20C292.145 20 288.545 23.384 287.105 25.616H286.889L286.385 20.792H276.881C277.025 23.888 277.169 27.632 277.169 32.024V56Z" fill="#191A35"/>
|
15 |
+
<path d="M342.036 20.792L341.676 24.968H341.532C339.732 22.088 336.708 20 331.884 20C323.244 20 315.9 27.2 315.9 38.504C315.9 48.656 322.092 55.712 330.804 55.712C334.836 55.712 338.22 54.056 340.308 51.104H340.452V53.408C340.452 59.888 336.492 62.696 331.308 62.696C327.204 62.696 323.316 61.328 321.084 60.032L318.924 68.312C322.092 70.112 326.988 71.048 331.596 71.048C336.78 71.048 342.036 70.04 345.924 66.728C349.884 63.2 351.252 57.656 351.252 50.888V31.232C351.252 25.976 351.396 23.024 351.54 20.792H342.036ZM340.308 40.304C340.308 41.24 340.236 42.392 339.948 43.184C339.228 45.776 336.996 47.648 334.188 47.648C329.58 47.648 326.988 43.544 326.988 38.288C326.988 31.88 330.228 28.28 334.188 28.28C337.212 28.28 339.3 30.224 340.092 33.104C340.236 33.68 340.308 34.4 340.308 35.12V40.304Z" fill="#191A35"/>
|
16 |
+
<path d="M388.473 56C388.113 54.056 387.969 50.816 387.969 47.432V35.192C387.969 26.912 384.225 20 372.489 20C366.081 20 361.257 21.728 358.809 23.096L360.825 30.152C363.129 28.712 366.945 27.488 370.545 27.488C375.945 27.488 376.953 30.152 376.953 32.024V32.528C364.497 32.456 356.289 36.848 356.289 45.992C356.289 51.608 360.537 56.792 367.665 56.792C371.841 56.792 375.441 55.28 377.745 52.472H377.961L378.609 56H388.473ZM377.313 43.184C377.313 43.832 377.241 44.48 377.097 45.056C376.377 47.288 374.145 49.088 371.409 49.088C368.961 49.088 367.089 47.72 367.089 44.912C367.089 40.664 371.553 39.296 377.313 39.368V43.184Z" fill="#191A35"/>
|
17 |
+
<path d="M419.312 20.792L418.952 24.968H418.808C417.008 22.088 413.984 20 409.16 20C400.52 20 393.176 27.2 393.176 38.504C393.176 48.656 399.368 55.712 408.08 55.712C412.112 55.712 415.496 54.056 417.584 51.104H417.728V53.408C417.728 59.888 413.768 62.696 408.584 62.696C404.48 62.696 400.592 61.328 398.36 60.032L396.2 68.312C399.368 70.112 404.264 71.048 408.872 71.048C414.056 71.048 419.312 70.04 423.2 66.728C427.16 63.2 428.528 57.656 428.528 50.888V31.232C428.528 25.976 428.672 23.024 428.816 20.792H419.312ZM417.584 40.304C417.584 41.24 417.512 42.392 417.224 43.184C416.504 45.776 414.272 47.648 411.464 47.648C406.856 47.648 404.264 43.544 404.264 38.288C404.264 31.88 407.504 28.28 411.464 28.28C414.488 28.28 416.576 30.224 417.368 33.104C417.512 33.68 417.584 34.4 417.584 35.12V40.304Z" fill="#191A35"/>
|
18 |
+
<path d="M466.973 41.888C467.117 41.096 467.333 39.44 467.333 37.568C467.333 28.856 463.013 20 451.637 20C439.397 20 433.853 29.864 433.853 38.792C433.853 49.808 440.693 56.72 452.645 56.72C457.397 56.72 461.789 56 465.389 54.56L463.949 47.144C460.997 48.08 457.973 48.584 454.229 48.584C449.117 48.584 444.653 46.424 444.293 41.888H466.973ZM444.221 34.4C444.509 31.448 446.381 27.272 450.989 27.272C456.029 27.272 457.181 31.736 457.181 34.4H444.221Z" fill="#191A35"/>
|
19 |
+
</svg>
|
assets/js/admin-widget-settings.js
CHANGED
@@ -1,68 +1,68 @@
|
|
1 |
-
(
|
2 |
-
function ( $ ) {
|
3 |
-
|
4 |
-
// Add Color Picker to all inputs that have 'color-field' class.
|
5 |
-
$( function () {
|
6 |
-
init_color_picker();
|
7 |
-
init_multiselect();
|
8 |
-
$( document ).on( 'widget-updated widget-added', function (e) {
|
9 |
-
init_color_picker();
|
10 |
-
init_multiselect();
|
11 |
-
} );
|
12 |
-
$( document ).on( 'change', '.exactmetrics-save-on-change', function () {
|
13 |
-
save_and_refresh_form( $( this ).closest( '.widget' ) );
|
14 |
-
} );
|
15 |
-
} );
|
16 |
-
|
17 |
-
function init_color_picker() {
|
18 |
-
var timeout;
|
19 |
-
$( '#widgets-right .exactmetrics-color-field' ).wpColorPicker( {
|
20 |
-
change: function ( event, ui ) {
|
21 |
-
if ( timeout ) {
|
22 |
-
clearTimeout( timeout );
|
23 |
-
}
|
24 |
-
timeout = setTimeout( function () {
|
25 |
-
$( event.target ).trigger( 'change' );
|
26 |
-
}, 300 );
|
27 |
-
},
|
28 |
-
} );
|
29 |
-
}
|
30 |
-
|
31 |
-
function save_and_refresh_form( widget ) {
|
32 |
-
if ( wpWidgets && 'undefined' !== typeof wpWidgets.save ) {
|
33 |
-
wpWidgets.save( widget, 0, 0 );
|
34 |
-
}
|
35 |
-
}
|
36 |
-
|
37 |
-
function init_multiselect() {
|
38 |
-
if ( ! jQuery.fn.select300 ) {
|
39 |
-
return;
|
40 |
-
}
|
41 |
-
$('#widgets-right .exactmetrics-multiselect').select300({
|
42 |
-
ajax: {
|
43 |
-
type: 'POST',
|
44 |
-
url: ajaxurl,
|
45 |
-
delay: 250,
|
46 |
-
width: 'resolve',
|
47 |
-
data: function (params) {
|
48 |
-
var taxonomy = $(this).data('taxonomy');
|
49 |
-
return {
|
50 |
-
taxonomy: taxonomy,
|
51 |
-
keyword: params.term,
|
52 |
-
action: 'exactmetrics_get_terms',
|
53 |
-
nonce: exactmetrics_pp.nonce,
|
54 |
-
};
|
55 |
-
},
|
56 |
-
processResults: function (data) {
|
57 |
-
return {
|
58 |
-
results: data.data
|
59 |
-
};
|
60 |
-
},
|
61 |
-
dataType: 'json'
|
62 |
-
}
|
63 |
-
});
|
64 |
-
|
65 |
-
}
|
66 |
-
|
67 |
-
}
|
68 |
-
)( jQuery );
|
1 |
+
(
|
2 |
+
function ( $ ) {
|
3 |
+
|
4 |
+
// Add Color Picker to all inputs that have 'color-field' class.
|
5 |
+
$( function () {
|
6 |
+
init_color_picker();
|
7 |
+
init_multiselect();
|
8 |
+
$( document ).on( 'widget-updated widget-added', function (e) {
|
9 |
+
init_color_picker();
|
10 |
+
init_multiselect();
|
11 |
+
} );
|
12 |
+
$( document ).on( 'change', '.exactmetrics-save-on-change', function () {
|
13 |
+
save_and_refresh_form( $( this ).closest( '.widget' ) );
|
14 |
+
} );
|
15 |
+
} );
|
16 |
+
|
17 |
+
function init_color_picker() {
|
18 |
+
var timeout;
|
19 |
+
$( '#widgets-right .exactmetrics-color-field' ).wpColorPicker( {
|
20 |
+
change: function ( event, ui ) {
|
21 |
+
if ( timeout ) {
|
22 |
+
clearTimeout( timeout );
|
23 |
+
}
|
24 |
+
timeout = setTimeout( function () {
|
25 |
+
$( event.target ).trigger( 'change' );
|
26 |
+
}, 300 );
|
27 |
+
},
|
28 |
+
} );
|
29 |
+
}
|
30 |
+
|
31 |
+
function save_and_refresh_form( widget ) {
|
32 |
+
if ( wpWidgets && 'undefined' !== typeof wpWidgets.save ) {
|
33 |
+
wpWidgets.save( widget, 0, 0 );
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
function init_multiselect() {
|
38 |
+
if ( ! jQuery.fn.select300 ) {
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
$('#widgets-right .exactmetrics-multiselect').select300({
|
42 |
+
ajax: {
|
43 |
+
type: 'POST',
|
44 |
+
url: ajaxurl,
|
45 |
+
delay: 250,
|
46 |
+
width: 'resolve',
|
47 |
+
data: function (params) {
|
48 |
+
var taxonomy = $(this).data('taxonomy');
|
49 |
+
return {
|
50 |
+
taxonomy: taxonomy,
|
51 |
+
keyword: params.term,
|
52 |
+
action: 'exactmetrics_get_terms',
|
53 |
+
nonce: exactmetrics_pp.nonce,
|
54 |
+
};
|
55 |
+
},
|
56 |
+
processResults: function (data) {
|
57 |
+
return {
|
58 |
+
results: data.data
|
59 |
+
};
|
60 |
+
},
|
61 |
+
dataType: 'json'
|
62 |
+
}
|
63 |
+
});
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
}
|
68 |
+
)( jQuery );
|
assets/js/frontend-gtag.js
CHANGED
@@ -1,829 +1,829 @@
|
|
1 |
-
/**
|
2 |
-
* Developer's Notice:
|
3 |
-
*
|
4 |
-
* Note: JS in this file (and this file itself) is not guaranteed backwards compatibility. JS can be added, changed or removed at any time without notice.
|
5 |
-
* For more information see the `Backwards Compatibility Guidelines for Developers` section of the README.md file.
|
6 |
-
*/
|
7 |
-
/**
|
8 |
-
* Handles:
|
9 |
-
* - JS Events handling
|
10 |
-
*
|
11 |
-
* @since 7.15.0
|
12 |
-
*/
|
13 |
-
var ExactMetrics = function () {
|
14 |
-
/* ExactMetrics JS events tracking works on all major browsers, including IE starting at IE 7, via polyfills for any major JS function used that
|
15 |
-
is not supported by at least 95% of the global and/or US browser marketshare. Currently, IE 7 & 8 which as of 2/14/17 have under 0.25% global marketshare, require
|
16 |
-
us to polyfill Array.prototype.lastIndexOf, and if they continue to drop, we might remove this polyfill at some point. In that case note that events tracking
|
17 |
-
for IE 7/8 will continue to work, with the exception of events tracking of downloads. */
|
18 |
-
var lastClicked = [];
|
19 |
-
var internalAsOutboundCategory = '';
|
20 |
-
var beforeUnloadChanged = false;
|
21 |
-
|
22 |
-
this.setLastClicked = function ( valuesArray, fieldsArray, tracked ) {
|
23 |
-
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
24 |
-
fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : [];
|
25 |
-
tracked = typeof tracked !== 'undefined' ? tracked : false;
|
26 |
-
|
27 |
-
lastClicked.valuesArray = valuesArray;
|
28 |
-
lastClicked.fieldsArray = fieldsArray;
|
29 |
-
};
|
30 |
-
|
31 |
-
this.getLastClicked = function () {
|
32 |
-
return lastClicked;
|
33 |
-
};
|
34 |
-
|
35 |
-
this.setInternalAsOutboundCategory = function ( category ) {
|
36 |
-
internalAsOutboundCategory = category;
|
37 |
-
};
|
38 |
-
|
39 |
-
this.getInternalAsOutboundCategory = function () {
|
40 |
-
return internalAsOutboundCategory;
|
41 |
-
};
|
42 |
-
|
43 |
-
this.sendEvent = function ( type, action, fieldsArray ) {
|
44 |
-
__gtagTrackerSend( type, action, fieldsArray, [] );
|
45 |
-
};
|
46 |
-
|
47 |
-
function __gtagTrackerIsDebug() {
|
48 |
-
if ( window.exactmetrics_debug_mode ) {
|
49 |
-
return true;
|
50 |
-
} else {
|
51 |
-
return false;
|
52 |
-
}
|
53 |
-
}
|
54 |
-
|
55 |
-
function cloneFields( fields, allowedKeys, disallowedKeys ) {
|
56 |
-
var clone = {};
|
57 |
-
|
58 |
-
for ( var key in fields ) {
|
59 |
-
if ( ! fields.hasOwnProperty( key ) ) {
|
60 |
-
continue
|
61 |
-
}
|
62 |
-
|
63 |
-
if ( allowedKeys && allowedKeys.indexOf( key ) === -1 ) {
|
64 |
-
continue
|
65 |
-
}
|
66 |
-
|
67 |
-
if ( disallowedKeys && disallowedKeys.indexOf( key ) > -1 ) {
|
68 |
-
continue
|
69 |
-
}
|
70 |
-
|
71 |
-
clone[ key ] = fields[ key ];
|
72 |
-
}
|
73 |
-
|
74 |
-
return clone;
|
75 |
-
}
|
76 |
-
|
77 |
-
function __gtagMaybeTrackerV4( type, action, fieldsArray ) {
|
78 |
-
if ( ! exactmetrics_frontend.v4_id || type !== 'event' ) {
|
79 |
-
return;
|
80 |
-
}
|
81 |
-
|
82 |
-
var eventCategory = fieldsArray.event_category || '';
|
83 |
-
|
84 |
-
var fieldsToRemove = [
|
85 |
-
'event_name',
|
86 |
-
'event_category',
|
87 |
-
'event_label',
|
88 |
-
'value',
|
89 |
-
];
|
90 |
-
|
91 |
-
var fields = cloneFields( fieldsArray, null, fieldsToRemove );
|
92 |
-
fields.action = action;
|
93 |
-
|
94 |
-
var eventMap = {
|
95 |
-
'outbound-link': 'click',
|
96 |
-
'download': 'file_download',
|
97 |
-
};
|
98 |
-
|
99 |
-
__gtagTracker( type, eventMap[ eventCategory ] || eventCategory.replace( '-', '_' ), fields );
|
100 |
-
}
|
101 |
-
|
102 |
-
function __gtagMaybeTrackerUA( type, action, fieldsArray ) {
|
103 |
-
if ( ! exactmetrics_frontend.ua ) {
|
104 |
-
return;
|
105 |
-
}
|
106 |
-
|
107 |
-
var allowedFields = [
|
108 |
-
'event_category',
|
109 |
-
'event_label',
|
110 |
-
'value',
|
111 |
-
];
|
112 |
-
|
113 |
-
var uaFields = cloneFields(fieldsArray, allowedFields);
|
114 |
-
uaFields.send_to = exactmetrics_frontend.ua
|
115 |
-
|
116 |
-
__gtagTracker( type, action, uaFields );
|
117 |
-
}
|
118 |
-
|
119 |
-
function __gtagTrackerSendDual( type, action, fieldsArray, valuesArray ) {
|
120 |
-
type = typeof type !== 'undefined' ? type : 'event';
|
121 |
-
action = typeof action !== 'undefined' ? action : '';
|
122 |
-
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
123 |
-
fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : {};
|
124 |
-
|
125 |
-
__gtagMaybeTrackerUA( type, action, fieldsArray );
|
126 |
-
__gtagMaybeTrackerV4( type, action, fieldsArray );
|
127 |
-
|
128 |
-
lastClicked.valuesArray = valuesArray;
|
129 |
-
lastClicked.fieldsArray = fieldsArray;
|
130 |
-
lastClicked.fieldsArray.event_action = action;
|
131 |
-
lastClicked.tracked = true;
|
132 |
-
__gtagTrackerLog( 'Tracked: ' + valuesArray.type );
|
133 |
-
__gtagTrackerLog( lastClicked );
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* This attempts to be compatible with the gtag function.
|
138 |
-
*
|
139 |
-
* @see https://developers.google.com/analytics/devguides/collection/gtagjs
|
140 |
-
* @param type string Type of request, event, timing, config.
|
141 |
-
* @param action string Event action or UA for config.
|
142 |
-
* @param fieldsArray object The configuration object.
|
143 |
-
* @param valuesArray object The values for the log.
|
144 |
-
* @private
|
145 |
-
*/
|
146 |
-
function __gtagTrackerSend( type, action, fieldsArray, valuesArray ) {
|
147 |
-
type = typeof type !== 'undefined' ? type : 'event';
|
148 |
-
action = typeof action !== 'undefined' ? action : '';
|
149 |
-
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
150 |
-
fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : {};
|
151 |
-
|
152 |
-
__gtagTracker( type, action, fieldsArray );
|
153 |
-
|
154 |
-
lastClicked.valuesArray = valuesArray;
|
155 |
-
lastClicked.fieldsArray = fieldsArray;
|
156 |
-
lastClicked.fieldsArray.event_action = action;
|
157 |
-
lastClicked.tracked = true;
|
158 |
-
__gtagTrackerLog( 'Tracked: ' + valuesArray.type );
|
159 |
-
__gtagTrackerLog( lastClicked );
|
160 |
-
}
|
161 |
-
|
162 |
-
function __gtagTrackerNotSend( valuesArray ) {
|
163 |
-
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
164 |
-
|
165 |
-
lastClicked.valuesArray = valuesArray;
|
166 |
-
lastClicked.fieldsArray = [];
|
167 |
-
lastClicked.tracked = false;
|
168 |
-
__gtagTrackerLog( 'Not Tracked: ' + valuesArray.exit );
|
169 |
-
__gtagTrackerLog( lastClicked );
|
170 |
-
}
|
171 |
-
|
172 |
-
function __gtagTrackerLog( message ) {
|
173 |
-
if ( __gtagTrackerIsDebug() ) {
|
174 |
-
console.dir( message );
|
175 |
-
}
|
176 |
-
}
|
177 |
-
|
178 |
-
function __gtagTrackerStringTrim( x ) {
|
179 |
-
return x.replace( /^\s+|\s+$/gm, '' );
|
180 |
-
}
|
181 |
-
|
182 |
-
function __gtagTrackerGetDomain() {
|
183 |
-
var i = 0, currentdomain = document.domain, p = currentdomain.split( '.' ), s = '_gd' + (
|
184 |
-
new Date()
|
185 |
-
).getTime();
|
186 |
-
while ( i < ( p.length - 1 ) && document.cookie.indexOf( s + '=' + s ) == - 1 ) {
|
187 |
-
currentdomain = p.slice( - 1 - (
|
188 |
-
++ i
|
189 |
-
) ).join( '.' );
|
190 |
-
document.cookie = s + "=" + s + ";domain=" + currentdomain + ";";
|
191 |
-
}
|
192 |
-
document.cookie = s + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain=" + currentdomain + ";";
|
193 |
-
return currentdomain;
|
194 |
-
}
|
195 |
-
|
196 |
-
function __gtagTrackerGetExtension( extension ) {
|
197 |
-
extension = extension.toString();
|
198 |
-
extension = extension.substring( 0, (
|
199 |
-
extension.indexOf( "#" ) == - 1
|
200 |
-
) ? extension.length : extension.indexOf( "#" ) ); /* Remove the anchor at the end, if there is one */
|
201 |
-
extension = extension.substring( 0, (
|
202 |
-
extension.indexOf( "?" ) == - 1
|
203 |
-
) ? extension.length : extension.indexOf( "?" ) ); /* Remove the query after the file name, if there is one */
|
204 |
-
extension = extension.substring( extension.lastIndexOf( "/" ) + 1, extension.length ); /* Remove everything before the last slash in the path */
|
205 |
-
if ( extension.length > 0 && extension.indexOf( '.' ) !== - 1 ) { /* If there's a period left in the URL, then there's a extension. Else it is not a extension. */
|
206 |
-
extension = extension.substring( extension.indexOf( "." ) + 1 ); /* Remove everything but what's after the first period */
|
207 |
-
return extension;
|
208 |
-
} else {
|
209 |
-
return "";
|
210 |
-
}
|
211 |
-
}
|
212 |
-
|
213 |
-
function __gtagTrackerTrackedClick( event ) {
|
214 |
-
return event.which == 1 || event.which == 2 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
215 |
-
}
|
216 |
-
|
217 |
-
function __gtagTrackerGetDownloadExtensions() {
|
218 |
-
var download_extensions = [];
|
219 |
-
if ( typeof exactmetrics_frontend.download_extensions == 'string' ) {
|
220 |
-
download_extensions = exactmetrics_frontend.download_extensions.split( "," );
|
221 |
-
}
|
222 |
-
return download_extensions;
|
223 |
-
}
|
224 |
-
|
225 |
-
function __gtagTrackerGetInboundPaths() {
|
226 |
-
var inbound_paths = [];
|
227 |
-
if ( typeof exactmetrics_frontend.inbound_paths == 'string' ) {
|
228 |
-
inbound_paths = JSON.parse( exactmetrics_frontend.inbound_paths );
|
229 |
-
}
|
230 |
-
|
231 |
-
return inbound_paths;
|
232 |
-
}
|
233 |
-
|
234 |
-
function __gtagTrackerTrackedClickType( event ) {
|
235 |
-
if ( event.which == 1 ) {
|
236 |
-
return 'event.which=1';
|
237 |
-
} else if ( event.which == 2 ) {
|
238 |
-
return 'event.which=2';
|
239 |
-
} else if ( event.metaKey ) {
|
240 |
-
return 'metaKey';
|
241 |
-
} else if ( event.ctrlKey ) {
|
242 |
-
return 'ctrlKey';
|
243 |
-
} else if ( event.shiftKey ) {
|
244 |
-
return 'shiftKey';
|
245 |
-
} else if ( event.altKey ) {
|
246 |
-
return 'altKey';
|
247 |
-
} else {
|
248 |
-
return '';
|
249 |
-
}
|
250 |
-
}
|
251 |
-
|
252 |
-
function __gtagTrackerLinkType( el ) {
|
253 |
-
var download_extensions = __gtagTrackerGetDownloadExtensions();
|
254 |
-
var inbound_paths = __gtagTrackerGetInboundPaths();
|
255 |
-
var type = 'unknown';
|
256 |
-
var link = el.href;
|
257 |
-
var extension = __gtagTrackerGetExtension( el.href );
|
258 |
-
var currentdomain = __gtagTrackerGetDomain();
|
259 |
-
var hostname = el.hostname;
|
260 |
-
var protocol = el.protocol;
|
261 |
-
var pathname = el.pathname;
|
262 |
-
link = link.toString();
|
263 |
-
var index, len;
|
264 |
-
var category = el.getAttribute( "data-vars-ga-category" );
|
265 |
-
|
266 |
-
if ( category ) {
|
267 |
-
return category;
|
268 |
-
}
|
269 |
-
|
270 |
-
if ( link.match( /^javascript\:/i ) ) {
|
271 |
-
type = 'internal'; /* if it's a JS link, it's internal */
|
272 |
-
} else if ( protocol && protocol.length > 0 && (
|
273 |
-
__gtagTrackerStringTrim( protocol ) == 'tel' || __gtagTrackerStringTrim( protocol ) == 'tel:'
|
274 |
-
) ) { /* If it's a telephone link */
|
275 |
-
type = "tel";
|
276 |
-
} else if ( protocol && protocol.length > 0 && (
|
277 |
-
__gtagTrackerStringTrim( protocol ) == 'mailto' || __gtagTrackerStringTrim( protocol ) == 'mailto:'
|
278 |
-
) ) { /* If it's a email */
|
279 |
-
type = "mailto";
|
280 |
-
} else if ( hostname && currentdomain && hostname.length > 0 && currentdomain.length > 0 && !hostname.endsWith( '.' + currentdomain ) && hostname !== currentdomain ) { /* If it's a outbound */
|
281 |
-
type = "external";
|
282 |
-
} else if ( pathname && JSON.stringify( inbound_paths ) != "{}" && pathname.length > 0 ) { /* If it's an internal as outbound */
|
283 |
-
var inbound_paths_length = inbound_paths.length;
|
284 |
-
for ( var inbound_paths_index = 0; inbound_paths_index < inbound_paths_length; inbound_paths_index ++ ) {
|
285 |
-
if ( inbound_paths[inbound_paths_index].path && inbound_paths[inbound_paths_index].label && inbound_paths[inbound_paths_index].path.length > 0 && inbound_paths[inbound_paths_index].label.length > 0 && pathname.startsWith( inbound_paths[inbound_paths_index].path ) ) {
|
286 |
-
type = "internal-as-outbound";
|
287 |
-
internalAsOutboundCategory = "outbound-link-" + inbound_paths[inbound_paths_index].label;
|
288 |
-
break;
|
289 |
-
}
|
290 |
-
}
|
291 |
-
/* Enable window.exactmetrics_experimental_mode at your own risk. We might eventually remove it. Also you may/can/will burn through GA quota for your property quickly. */
|
292 |
-
} else if ( hostname && window.exactmetrics_experimental_mode && hostname.length > 0 && document.domain.length > 0 && hostname !== document.domain ) { /* If it's a cross-hostname link */
|
293 |
-
type = "cross-hostname";
|
294 |
-
}
|
295 |
-
|
296 |
-
if ( extension && (
|
297 |
-
type === 'unknown' || 'external' === type
|
298 |
-
) && download_extensions.length > 0 && extension.length > 0 ) { /* If it's a download */
|
299 |
-
for ( index = 0, len = download_extensions.length; index < len; ++ index ) {
|
300 |
-
if ( download_extensions[index].length > 0 && (
|
301 |
-
link.endsWith( download_extensions[index] ) || download_extensions[index] == extension
|
302 |
-
) ) {
|
303 |
-
type = "download";
|
304 |
-
break;
|
305 |
-
}
|
306 |
-
}
|
307 |
-
}
|
308 |
-
|
309 |
-
if ( type === 'unknown' ) {
|
310 |
-
type = 'internal';
|
311 |
-
}
|
312 |
-
return type;
|
313 |
-
}
|
314 |
-
|
315 |
-
function __gtagTrackerLinkTarget( el, event ) {
|
316 |
-
|
317 |
-
/* Is actual target set and not _(self|parent|top)? */
|
318 |
-
var target = (
|
319 |
-
el.target && !el.target.match( /^_(self|parent|top)$/i )
|
320 |
-
) ? el.target : false;
|
321 |
-
|
322 |
-
/* Assume a target if Ctrl|shift|meta-click */
|
323 |
-
if ( event.ctrlKey || event.shiftKey || event.metaKey || event.which == 2 ) {
|
324 |
-
target = "_blank";
|
325 |
-
}
|
326 |
-
return target;
|
327 |
-
}
|
328 |
-
|
329 |
-
function __gtagTrackerGetTitle( el ) {
|
330 |
-
if ( el.getAttribute( "data-vars-ga-label" ) && el.getAttribute( "data-vars-ga-label" ).replace( /\n/ig, '' ) ) {
|
331 |
-
return el.getAttribute( "data-vars-ga-label" ).replace( /\n/ig, '' );
|
332 |
-
} else if ( el.title && el.title.replace( /\n/ig, '' ) ) {
|
333 |
-
return el.title.replace( /\n/ig, '' );
|
334 |
-
} else if ( el.innerText && el.innerText.replace( /\n/ig, '' ) ) {
|
335 |
-
return el.innerText.replace( /\n/ig, '' );
|
336 |
-
} else if ( el.getAttribute( 'aria-label' ) && el.getAttribute( 'aria-label' ).replace( /\n/ig, '' ) ) {
|
337 |
-
return el.getAttribute( 'aria-label' ).replace( /\n/ig, '' );
|
338 |
-
} else if ( el.alt && el.alt.replace( /\n/ig, '' ) ) {
|
339 |
-
return el.alt.replace( /\n/ig, '' );
|
340 |
-
} else if ( el.textContent && el.textContent.replace( /\n/ig, '' ) ) {
|
341 |
-
return el.textContent.replace( /\n/ig, '' );
|
342 |
-
} else {
|
343 |
-
return undefined;
|
344 |
-
}
|
345 |
-
}
|
346 |
-
|
347 |
-
function __gtagTrackerGetInnerTitle( el ) {
|
348 |
-
var children = el.children;
|
349 |
-
var count = 0;
|
350 |
-
var child;
|
351 |
-
var value;
|
352 |
-
for ( var i = 0; i < children.length; i ++ ) {
|
353 |
-
child = children[i];
|
354 |
-
value = __gtagTrackerGetTitle( child );
|
355 |
-
if ( value ) {
|
356 |
-
return value;
|
357 |
-
}
|
358 |
-
/* max search 100 elements to ensure performance */
|
359 |
-
if ( count == 99 ) {
|
360 |
-
return undefined;
|
361 |
-
}
|
362 |
-
count ++;
|
363 |
-
}
|
364 |
-
return undefined;
|
365 |
-
}
|
366 |
-
|
367 |
-
function __gtagTrackerClickEvent( event ) {
|
368 |
-
var el = event.srcElement || event.target;
|
369 |
-
var valuesArray = [];
|
370 |
-
var fieldsArray;
|
371 |
-
|
372 |
-
/* Start Values Array */
|
373 |
-
valuesArray.el = el;
|
374 |
-
valuesArray.click_type = __gtagTrackerTrackedClickType( event );
|
375 |
-
|
376 |
-
/* If GA is blocked or not loaded, or not main|middle|touch click then don't track */
|
377 |
-
if ( 'undefined' === typeof __gtagTracker || ! __gtagTrackerTrackedClick( event ) ) {
|
378 |
-
valuesArray.exit = 'loaded';
|
379 |
-
__gtagTrackerNotSend( valuesArray );
|
380 |
-
return;
|
381 |
-
}
|
382 |
-
|
383 |
-
/* Loop up the DOM tree through parent elements if clicked element is not a link (eg: an image inside a link) */
|
384 |
-
while ( el && (
|
385 |
-
typeof el.tagName == 'undefined' || el.tagName.toLowerCase() != 'a' || !el.href
|
386 |
-
) ) {
|
387 |
-
el = el.parentNode;
|
388 |
-
}
|
389 |
-
|
390 |
-
/* if a link with valid href has been clicked */
|
391 |
-
if ( el && el.href && !el.hasAttribute( 'xlink:href' ) ) {
|
392 |
-
var link = el.href; /* What link are we tracking */
|
393 |
-
var extension = __gtagTrackerGetExtension( el.href ); /* What extension is this link */
|
394 |
-
var download_extensions = __gtagTrackerGetDownloadExtensions(); /* Let's get the extensions to track */
|
395 |
-
var inbound_paths = __gtagTrackerGetInboundPaths(); /* Let's get the internal paths to track */
|
396 |
-
var home_url = exactmetrics_frontend.home_url; /* Let's get the url to compare for external/internal use */
|
397 |
-
var currentdomain = __gtagTrackerGetDomain(); /* What domain are we on? */
|
398 |
-
var type = __gtagTrackerLinkType( el ); /* What type of link is this? */
|
399 |
-
var target = __gtagTrackerLinkTarget( el, event ); /* Is a new tab/window being opened? */
|
400 |
-
var action = el.getAttribute( "data-vars-ga-action" );
|
401 |
-
var label = el.getAttribute( "data-vars-ga-label" );
|
402 |
-
|
403 |
-
/* Element */
|
404 |
-
valuesArray.el = el; /* el is an a element so we can parse it */
|
405 |
-
valuesArray.el_href = el.href; /* "http://example.com:3000/pathname/?search=test#hash" */
|
406 |
-
valuesArray.el_protocol = el.protocol; /* "http:" */
|
407 |
-
valuesArray.el_hostname = el.hostname; /* "example.com" */
|
408 |
-
valuesArray.el_port = el.port; /* "3000" */
|
409 |
-
valuesArray.el_pathname = el.pathname; /* "/pathname/" */
|
410 |
-
valuesArray.el_search = el.search; /* "?search=test" */
|
411 |
-
valuesArray.el_hash = el.hash; /* "#hash" */
|
412 |
-
valuesArray.el_host = el.host; /* "example.com:3000" */
|
413 |
-
valuesArray.el_classes = el.getAttribute('class')
|
414 |
-
valuesArray.el_id = el.id
|
415 |
-
|
416 |
-
/* Settings */
|
417 |
-
valuesArray.debug_mode = __gtagTrackerIsDebug(); /* "example.com:3000" */
|
418 |
-
valuesArray.download_extensions = download_extensions; /* Let's get the extensions to track */
|
419 |
-
valuesArray.inbound_paths = inbound_paths; /* Let's get the internal paths to track */
|
420 |
-
valuesArray.home_url = home_url; /* Let's get the url to compare for external/internal use */
|
421 |
-
|
422 |
-
/* Parsed/Logic */
|
423 |
-
valuesArray.link = link; /* What link are we tracking */
|
424 |
-
valuesArray.extension = extension; /* What extension is this link */
|
425 |
-
valuesArray.type = type; /* What type of link is this */
|
426 |
-
valuesArray.target = target; /* Is a new tab/window being opened? */
|
427 |
-
valuesArray.title = __gtagTrackerGetTitle( el ); /* Try link title, then text content */
|
428 |
-
|
429 |
-
/* only find innerTitle if we need one */
|
430 |
-
if ( ! valuesArray.label && !valuesArray.title ) {
|
431 |
-
valuesArray.title = __gtagTrackerGetInnerTitle( el );
|
432 |
-
}
|
433 |
-
|
434 |
-
/* Let's track everything but internals (that aren't internal-as-externals) and javascript */
|
435 |
-
if ( type !== 'internal' && type !== 'javascript' ) {
|
436 |
-
|
437 |
-
var __gtagTrackerHitBackRun = false; /* Tracker has not yet run */
|
438 |
-
|
439 |
-
/* HitCallback to open link in same window after tracker */
|
440 |
-
var __gtagTrackerHitBack = function () {
|
441 |
-
/* Run the hitback only once */
|
442 |
-
if ( __gtagTrackerHitBackRun ) {
|
443 |
-
return;
|
444 |
-
}
|
445 |
-
maybePreventBeforeUnload();
|
446 |
-
__gtagTrackerHitBackRun = true;
|
447 |
-
window.location.href = link;
|
448 |
-
};
|
449 |
-
|
450 |
-
var __gtagTrackerNoRedirectExternal = function () {
|
451 |
-
valuesArray.exit = 'external';
|
452 |
-
__gtagTrackerNotSend( valuesArray );
|
453 |
-
};
|
454 |
-
|
455 |
-
var __gtagTrackerNoRedirectInboundAsExternal = function () {
|
456 |
-
valuesArray.exit = 'internal-as-outbound';
|
457 |
-
__gtagTrackerNotSend( valuesArray );
|
458 |
-
};
|
459 |
-
var __gtagTrackerNoRedirectCrossHostname = function () {
|
460 |
-
valuesArray.exit = 'cross-hostname';
|
461 |
-
__gtagTrackerNotSend( valuesArray );
|
462 |
-
};
|
463 |
-
|
464 |
-
if ( target || type == 'mailto' || type == 'tel' ) { /* If target opens a new window then just track */
|
465 |
-
if ( type == 'download' ) {
|
466 |
-
fieldsArray = {
|
467 |
-
event_category: 'download',
|
468 |
-
event_label: label || valuesArray.title,
|
469 |
-
file_extension: valuesArray.extension,
|
470 |
-
file_name: valuesArray.link.replace(/^.*\//g, ''),
|
471 |
-
link_text: label || valuesArray.title,
|
472 |
-
link_url: link,
|
473 |
-
link_domain: valuesArray.el_hostname,
|
474 |
-
link_classes: valuesArray.el_classes,
|
475 |
-
link_id: valuesArray.el_id,
|
476 |
-
};
|
477 |
-
} else if ( type == 'tel' ) {
|
478 |
-
fieldsArray = {
|
479 |
-
event_category: 'tel',
|
480 |
-
event_label: label || valuesArray.title.replace( 'tel:', '' ),
|
481 |
-
tel_number: link.replace( 'tel:', '' ),
|
482 |
-
link_text: label || valuesArray.title,
|
483 |
-
link_url: link,
|
484 |
-
link_classes: valuesArray.el_classes,
|
485 |
-
link_id: valuesArray.el_id,
|
486 |
-
};
|
487 |
-
} else if ( type == 'mailto' ) {
|
488 |
-
fieldsArray = {
|
489 |
-
event_category: 'mailto',
|
490 |
-
event_label: label || valuesArray.title.replace( 'mailto:', '' ),
|
491 |
-
email_address: link.replace( 'mailto:', '' ),
|
492 |
-
link_text: label || valuesArray.title.replace( 'mailto:', ''),
|
493 |
-
link_url: link,
|
494 |
-
link_classes: valuesArray.el_classes,
|
495 |
-
link_id: valuesArray.el_id,
|
496 |
-
};
|
497 |
-
} else if ( type == 'internal-as-outbound' ) {
|
498 |
-
fieldsArray = {
|
499 |
-
event_category: internalAsOutboundCategory,
|
500 |
-
event_label: label || valuesArray.title,
|
501 |
-
event_name: 'click',
|
502 |
-
is_affiliate_link: true,
|
503 |
-
affiliate_label: internalAsOutboundCategory.replace('outbound-link-', ''),
|
504 |
-
link_text: label || valuesArray.title,
|
505 |
-
link_url: link,
|
506 |
-
link_domain: valuesArray.el_hostname,
|
507 |
-
link_classes: valuesArray.el_classes,
|
508 |
-
link_id: valuesArray.el_id,
|
509 |
-
outbound: true,
|
510 |
-
};
|
511 |
-
} else if ( type == 'external' ) {
|
512 |
-
fieldsArray = {
|
513 |
-
event_category: 'outbound-link',
|
514 |
-
event_label: label || valuesArray.title,
|
515 |
-
is_affiliate_link: false,
|
516 |
-
link_text: label || valuesArray.title,
|
517 |
-
link_url: link,
|
518 |
-
link_domain: valuesArray.el_hostname,
|
519 |
-
link_classes: valuesArray.el_classes,
|
520 |
-
link_id: valuesArray.el_id,
|
521 |
-
outbound: true,
|
522 |
-
};
|
523 |
-
} else if ( type == 'cross-hostname' ) {
|
524 |
-
fieldsArray = {
|
525 |
-
event_category: 'cross-hostname',
|
526 |
-
event_label: label || valuesArray.title,
|
527 |
-
link_text: label || valuesArray.title,
|
528 |
-
link_url: link,
|
529 |
-
link_domain: valuesArray.el_hostname,
|
530 |
-
link_classes: valuesArray.el_classes,
|
531 |
-
link_id: valuesArray.el_id,
|
532 |
-
};
|
533 |
-
}
|
534 |
-
|
535 |
-
if ( fieldsArray ) {
|
536 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
537 |
-
} else {
|
538 |
-
if ( type && type != 'internal' ) {
|
539 |
-
fieldsArray = {
|
540 |
-
event_category: type,
|
541 |
-
event_label: label || valuesArray.title,
|
542 |
-
link_text: label || valuesArray.title,
|
543 |
-
link_url: link,
|
544 |
-
link_domain: valuesArray.el_hostname,
|
545 |
-
link_classes: valuesArray.el_classes,
|
546 |
-
link_id: valuesArray.el_id,
|
547 |
-
};
|
548 |
-
|
549 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
550 |
-
} else {
|
551 |
-
valuesArray.exit = 'type';
|
552 |
-
__gtagTrackerNotSend( valuesArray );
|
553 |
-
}
|
554 |
-
}
|
555 |
-
} else {
|
556 |
-
/* Prevent standard click, track then open */
|
557 |
-
if ( type != 'cross-hostname' && type != 'external' && type != 'internal-as-outbound' ) {
|
558 |
-
if ( !event.defaultPrevented ) {
|
559 |
-
if ( event.preventDefault ) {
|
560 |
-
event.preventDefault();
|
561 |
-
} else {
|
562 |
-
event.returnValue = false;
|
563 |
-
}
|
564 |
-
}
|
565 |
-
}
|
566 |
-
|
567 |
-
if ( type == 'download' ) {
|
568 |
-
fieldsArray = {
|
569 |
-
event_category: 'download',
|
570 |
-
event_label: label || valuesArray.title,
|
571 |
-
event_callback: __gtagTrackerHitBack,
|
572 |
-
file_extension: valuesArray.extension,
|
573 |
-
file_name: valuesArray.link.replace(/^.*\//g, ''),
|
574 |
-
link_text: label || valuesArray.title,
|
575 |
-
link_url: link,
|
576 |
-
link_domain: valuesArray.el_hostname,
|
577 |
-
link_classes: valuesArray.el_classes,
|
578 |
-
link_id: valuesArray.el_id,
|
579 |
-
};
|
580 |
-
|
581 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
582 |
-
} else if ( type == 'internal-as-outbound' ) {
|
583 |
-
beforeUnloadChanged = true;
|
584 |
-
window.onbeforeunload = function ( e ) {
|
585 |
-
if ( !event.defaultPrevented ) {
|
586 |
-
if ( event.preventDefault ) {
|
587 |
-
event.preventDefault();
|
588 |
-
} else {
|
589 |
-
event.returnValue = false;
|
590 |
-
}
|
591 |
-
}
|
592 |
-
|
593 |
-
fieldsArray = {
|
594 |
-
event_category: internalAsOutboundCategory,
|
595 |
-
event_label: label || valuesArray.title,
|
596 |
-
event_callback: __gtagTrackerHitBack,
|
597 |
-
is_affiliate_link: true,
|
598 |
-
affiliate_label: internalAsOutboundCategory.replace('outbound-link-', ''),
|
599 |
-
link_text: label || valuesArray.title,
|
600 |
-
link_url: link,
|
601 |
-
link_domain: valuesArray.el_hostname,
|
602 |
-
link_classes: valuesArray.el_classes,
|
603 |
-
link_id: valuesArray.el_id,
|
604 |
-
outbound: true,
|
605 |
-
};
|
606 |
-
|
607 |
-
if ( navigator.sendBeacon ) {
|
608 |
-
fieldsArray.transport = 'beacon';
|
609 |
-
}
|
610 |
-
|
611 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
612 |
-
|
613 |
-
setTimeout( __gtagTrackerHitBack, 1000 );
|
614 |
-
};
|
615 |
-
} else if ( type == 'external' ) {
|
616 |
-
beforeUnloadChanged = true;
|
617 |
-
window.onbeforeunload = function ( e ) {
|
618 |
-
if ( !event.defaultPrevented ) {
|
619 |
-
if ( event.preventDefault ) {
|
620 |
-
event.preventDefault();
|
621 |
-
} else {
|
622 |
-
event.returnValue = false;
|
623 |
-
}
|
624 |
-
}
|
625 |
-
|
626 |
-
fieldsArray = {
|
627 |
-
event_category: 'outbound-link',
|
628 |
-
event_label: label || valuesArray.title,
|
629 |
-
event_callback: __gtagTrackerHitBack,
|
630 |
-
is_affiliate_link: false,
|
631 |
-
link_text: label || valuesArray.title,
|
632 |
-
link_url: link,
|
633 |
-
link_domain: valuesArray.el_hostname,
|
634 |
-
link_classes: valuesArray.el_classes,
|
635 |
-
link_id: valuesArray.el_id,
|
636 |
-
outbound: true,
|
637 |
-
};
|
638 |
-
|
639 |
-
if ( navigator.sendBeacon ) {
|
640 |
-
fieldsArray.transport = 'beacon';
|
641 |
-
}
|
642 |
-
|
643 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
644 |
-
setTimeout( __gtagTrackerHitBack, 1000 );
|
645 |
-
};
|
646 |
-
} else if ( type == 'cross-hostname' ) {
|
647 |
-
beforeUnloadChanged = true;
|
648 |
-
window.onbeforeunload = function ( e ) {
|
649 |
-
if ( !event.defaultPrevented ) {
|
650 |
-
if ( event.preventDefault ) {
|
651 |
-
event.preventDefault();
|
652 |
-
} else {
|
653 |
-
event.returnValue = false;
|
654 |
-
}
|
655 |
-
}
|
656 |
-
|
657 |
-
fieldsArray = {
|
658 |
-
event_category: 'cross-hostname',
|
659 |
-
event_label: label || valuesArray.title,
|
660 |
-
event_callback: __gtagTrackerHitBack,
|
661 |
-
link_text: label || valuesArray.title,
|
662 |
-
link_url: link,
|
663 |
-
link_domain: valuesArray.el_hostname,
|
664 |
-
link_classes: valuesArray.el_classes,
|
665 |
-
link_id: valuesArray.el_id,
|
666 |
-
};
|
667 |
-
|
668 |
-
if ( navigator.sendBeacon ) {
|
669 |
-
fieldsArray.transport = 'beacon';
|
670 |
-
}
|
671 |
-
|
672 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
673 |
-
setTimeout( __gtagTrackerHitBack, 1000 );
|
674 |
-
};
|
675 |
-
} else {
|
676 |
-
if ( type && type !== 'internal' ) {
|
677 |
-
fieldsArray = {
|
678 |
-
event_category: type,
|
679 |
-
event_label: label || valuesArray.title,
|
680 |
-
event_callback: __gtagTrackerHitBack,
|
681 |
-
link_text: label || valuesArray.title,
|
682 |
-
link_url: link,
|
683 |
-
link_domain: valuesArray.el_hostname,
|
684 |
-
link_classes: valuesArray.el_classes,
|
685 |
-
link_id: valuesArray.el_id,
|
686 |
-
};
|
687 |
-
|
688 |
-
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
689 |
-
} else {
|
690 |
-
valuesArray.exit = 'type';
|
691 |
-
__gtagTrackerNotSend( valuesArray );
|
692 |
-
}
|
693 |
-
}
|
694 |
-
|
695 |
-
if ( type != 'external' && type != 'cross-hostname' && type != 'internal-as-outbound' ) {
|
696 |
-
/* Run event_callback again if GA takes longer than 1 second */
|
697 |
-
setTimeout( __gtagTrackerHitBack, 1000 );
|
698 |
-
} else {
|
699 |
-
if ( type == 'external' ) {
|
700 |
-
setTimeout( __gtagTrackerNoRedirectExternal, 1100 );
|
701 |
-
} else if ( type == 'cross-hostname' ) {
|
702 |
-
setTimeout( __gtagTrackerNoRedirectCrossHostname, 1100 );
|
703 |
-
} else {
|
704 |
-
setTimeout( __gtagTrackerNoRedirectInboundAsExternal, 1100 );
|
705 |
-
}
|
706 |
-
}
|
707 |
-
|
708 |
-
// Clear out the beforeunload event if it was set to avoid sending false events.
|
709 |
-
setTimeout( maybePreventBeforeUnload, 100 );
|
710 |
-
}
|
711 |
-
} else {
|
712 |
-
maybePreventBeforeUnload();
|
713 |
-
valuesArray.exit = 'internal';
|
714 |
-
__gtagTrackerNotSend( valuesArray );
|
715 |
-
}
|
716 |
-
} else {
|
717 |
-
valuesArray.exit = 'notlink';
|
718 |
-
__gtagTrackerNotSend( valuesArray );
|
719 |
-
}
|
720 |
-
}
|
721 |
-
|
722 |
-
var prevHash = window.location.hash;
|
723 |
-
|
724 |
-
function __gtagTrackerHashChangeEvent() {
|
725 |
-
/* Todo: Ready this section for JS unit testing */
|
726 |
-
if ( exactmetrics_frontend.hash_tracking === "true" && prevHash != window.location.hash && ( exactmetrics_frontend.ua || exactmetrics_frontend.v4_id ) ) {
|
727 |
-
prevHash = window.location.hash;
|
728 |
-
if ( exactmetrics_frontend.ua ) {
|
729 |
-
__gtagTracker( 'config', exactmetrics_frontend.ua, {
|
730 |
-
page_path: location.pathname + location.search + location.hash,
|
731 |
-
} );
|
732 |
-
}
|
733 |
-
|
734 |
-
if ( exactmetrics_frontend.v4_id ) {
|
735 |
-
__gtagTracker( 'config', exactmetrics_frontend.v4_id, {
|
736 |
-
page_path: location.pathname + location.search + location.hash,
|
737 |
-
} );
|
738 |
-
}
|
739 |
-
__gtagTrackerLog( "Hash change to: " + location.pathname + location.search + location.hash );
|
740 |
-
} else {
|
741 |
-
__gtagTrackerLog( "Hash change to (untracked): " + location.pathname + location.search + location.hash );
|
742 |
-
}
|
743 |
-
}
|
744 |
-
|
745 |
-
function maybePreventBeforeUnload() {
|
746 |
-
if ( beforeUnloadChanged ) {
|
747 |
-
window.onbeforeunload = null;
|
748 |
-
}
|
749 |
-
}
|
750 |
-
|
751 |
-
/* Attach the event to all clicks in the document after page has loaded */
|
752 |
-
var __gtagTrackerWindow = window;
|
753 |
-
if ( __gtagTrackerWindow.addEventListener ) {
|
754 |
-
__gtagTrackerWindow.addEventListener(
|
755 |
-
"load",
|
756 |
-
function () {
|
757 |
-
document.body.addEventListener(
|
758 |
-
"click",
|
759 |
-
__gtagTrackerClickEvent,
|
760 |
-
false
|
761 |
-
);
|
762 |
-
},
|
763 |
-
false
|
764 |
-
);
|
765 |
-
window.addEventListener( "hashchange", __gtagTrackerHashChangeEvent, false );
|
766 |
-
} else {
|
767 |
-
if ( __gtagTrackerWindow.attachEvent ) {
|
768 |
-
__gtagTrackerWindow.attachEvent(
|
769 |
-
"onload",
|
770 |
-
function () {
|
771 |
-
document.body.attachEvent( "onclick", __gtagTrackerClickEvent );
|
772 |
-
}
|
773 |
-
);
|
774 |
-
window.attachEvent( "onhashchange", __gtagTrackerHashChangeEvent );
|
775 |
-
}
|
776 |
-
}
|
777 |
-
|
778 |
-
if ( typeof String.prototype.endsWith !== 'function' ) {
|
779 |
-
String.prototype.endsWith = function ( suffix ) {
|
780 |
-
return this.indexOf( suffix, this.length - suffix.length ) !== - 1;
|
781 |
-
};
|
782 |
-
}
|
783 |
-
if ( typeof String.prototype.startsWith !== 'function' ) {
|
784 |
-
String.prototype.startsWith = function ( prefix ) {
|
785 |
-
return this.indexOf( prefix ) === 0;
|
786 |
-
};
|
787 |
-
}
|
788 |
-
|
789 |
-
if ( typeof Array.prototype.lastIndexOf !== 'function' ) {
|
790 |
-
Array.prototype.lastIndexOf = function ( searchElement /*, fromIndex*/ ) {
|
791 |
-
'use strict';
|
792 |
-
|
793 |
-
if ( this === void 0 || this === null ) {
|
794 |
-
throw new TypeError();
|
795 |
-
}
|
796 |
-
|
797 |
-
var n, k,
|
798 |
-
t = Object( this ),
|
799 |
-
len = t.length >>> 0; /* jshint ignore:line */
|
800 |
-
if ( len === 0 ) {
|
801 |
-
return - 1;
|
802 |
-
}
|
803 |
-
|
804 |
-
n = len - 1;
|
805 |
-
if ( arguments.length > 1 ) {
|
806 |
-
n = Number( arguments[1] );
|
807 |
-
if ( n != n ) {
|
808 |
-
n = 0;
|
809 |
-
} else if ( n != 0 && n != (
|
810 |
-
1 / 0
|
811 |
-
) && n != - (
|
812 |
-
1 / 0
|
813 |
-
) ) { /* jshint ignore:line */
|
814 |
-
n = (
|
815 |
-
n > 0 || - 1
|
816 |
-
) * Math.floor( Math.abs( n ) );
|
817 |
-
}
|
818 |
-
}
|
819 |
-
|
820 |
-
for ( k = n >= 0 ? Math.min( n, len - 1 ) : len - Math.abs( n ); k >= 0; k -- ) {
|
821 |
-
if ( k in t && t[k] === searchElement ) {
|
822 |
-
return k;
|
823 |
-
}
|
824 |
-
}
|
825 |
-
return - 1;
|
826 |
-
};
|
827 |
-
}
|
828 |
-
};
|
829 |
-
var ExactMetricsObject = new ExactMetrics();
|
1 |
+
/**
|
2 |
+
* Developer's Notice:
|
3 |
+
*
|
4 |
+
* Note: JS in this file (and this file itself) is not guaranteed backwards compatibility. JS can be added, changed or removed at any time without notice.
|
5 |
+
* For more information see the `Backwards Compatibility Guidelines for Developers` section of the README.md file.
|
6 |
+
*/
|
7 |
+
/**
|
8 |
+
* Handles:
|
9 |
+
* - JS Events handling
|
10 |
+
*
|
11 |
+
* @since 7.15.0
|
12 |
+
*/
|
13 |
+
var ExactMetrics = function () {
|
14 |
+
/* ExactMetrics JS events tracking works on all major browsers, including IE starting at IE 7, via polyfills for any major JS function used that
|
15 |
+
is not supported by at least 95% of the global and/or US browser marketshare. Currently, IE 7 & 8 which as of 2/14/17 have under 0.25% global marketshare, require
|
16 |
+
us to polyfill Array.prototype.lastIndexOf, and if they continue to drop, we might remove this polyfill at some point. In that case note that events tracking
|
17 |
+
for IE 7/8 will continue to work, with the exception of events tracking of downloads. */
|
18 |
+
var lastClicked = [];
|
19 |
+
var internalAsOutboundCategory = '';
|
20 |
+
var beforeUnloadChanged = false;
|
21 |
+
|
22 |
+
this.setLastClicked = function ( valuesArray, fieldsArray, tracked ) {
|
23 |
+
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
24 |
+
fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : [];
|
25 |
+
tracked = typeof tracked !== 'undefined' ? tracked : false;
|
26 |
+
|
27 |
+
lastClicked.valuesArray = valuesArray;
|
28 |
+
lastClicked.fieldsArray = fieldsArray;
|
29 |
+
};
|
30 |
+
|
31 |
+
this.getLastClicked = function () {
|
32 |
+
return lastClicked;
|
33 |
+
};
|
34 |
+
|
35 |
+
this.setInternalAsOutboundCategory = function ( category ) {
|
36 |
+
internalAsOutboundCategory = category;
|
37 |
+
};
|
38 |
+
|
39 |
+
this.getInternalAsOutboundCategory = function () {
|
40 |
+
return internalAsOutboundCategory;
|
41 |
+
};
|
42 |
+
|
43 |
+
this.sendEvent = function ( type, action, fieldsArray ) {
|
44 |
+
__gtagTrackerSend( type, action, fieldsArray, [] );
|
45 |
+
};
|
46 |
+
|
47 |
+
function __gtagTrackerIsDebug() {
|
48 |
+
if ( window.exactmetrics_debug_mode ) {
|
49 |
+
return true;
|
50 |
+
} else {
|
51 |
+
return false;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
function cloneFields( fields, allowedKeys, disallowedKeys ) {
|
56 |
+
var clone = {};
|
57 |
+
|
58 |
+
for ( var key in fields ) {
|
59 |
+
if ( ! fields.hasOwnProperty( key ) ) {
|
60 |
+
continue
|
61 |
+
}
|
62 |
+
|
63 |
+
if ( allowedKeys && allowedKeys.indexOf( key ) === -1 ) {
|
64 |
+
continue
|
65 |
+
}
|
66 |
+
|
67 |
+
if ( disallowedKeys && disallowedKeys.indexOf( key ) > -1 ) {
|
68 |
+
continue
|
69 |
+
}
|
70 |
+
|
71 |
+
clone[ key ] = fields[ key ];
|
72 |
+
}
|
73 |
+
|
74 |
+
return clone;
|
75 |
+
}
|
76 |
+
|
77 |
+
function __gtagMaybeTrackerV4( type, action, fieldsArray ) {
|
78 |
+
if ( ! exactmetrics_frontend.v4_id || type !== 'event' ) {
|
79 |
+
return;
|
80 |
+
}
|
81 |
+
|
82 |
+
var eventCategory = fieldsArray.event_category || '';
|
83 |
+
|
84 |
+
var fieldsToRemove = [
|
85 |
+
'event_name',
|
86 |
+
'event_category',
|
87 |
+
'event_label',
|
88 |
+
'value',
|
89 |
+
];
|
90 |
+
|
91 |
+
var fields = cloneFields( fieldsArray, null, fieldsToRemove );
|
92 |
+
fields.action = action;
|
93 |
+
|
94 |
+
var eventMap = {
|
95 |
+
'outbound-link': 'click',
|
96 |
+
'download': 'file_download',
|
97 |
+
};
|
98 |
+
|
99 |
+
__gtagTracker( type, eventMap[ eventCategory ] || eventCategory.replace( '-', '_' ), fields );
|
100 |
+
}
|
101 |
+
|
102 |
+
function __gtagMaybeTrackerUA( type, action, fieldsArray ) {
|
103 |
+
if ( ! exactmetrics_frontend.ua ) {
|
104 |
+
return;
|
105 |
+
}
|
106 |
+
|
107 |
+
var allowedFields = [
|
108 |
+
'event_category',
|
109 |
+
'event_label',
|
110 |
+
'value',
|
111 |
+
];
|
112 |
+
|
113 |
+
var uaFields = cloneFields(fieldsArray, allowedFields);
|
114 |
+
uaFields.send_to = exactmetrics_frontend.ua
|
115 |
+
|
116 |
+
__gtagTracker( type, action, uaFields );
|
117 |
+
}
|
118 |
+
|
119 |
+
function __gtagTrackerSendDual( type, action, fieldsArray, valuesArray ) {
|
120 |
+
type = typeof type !== 'undefined' ? type : 'event';
|
121 |
+
action = typeof action !== 'undefined' ? action : '';
|
122 |
+
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
123 |
+
fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : {};
|
124 |
+
|
125 |
+
__gtagMaybeTrackerUA( type, action, fieldsArray );
|
126 |
+
__gtagMaybeTrackerV4( type, action, fieldsArray );
|
127 |
+
|
128 |
+
lastClicked.valuesArray = valuesArray;
|
129 |
+
lastClicked.fieldsArray = fieldsArray;
|
130 |
+
lastClicked.fieldsArray.event_action = action;
|
131 |
+
lastClicked.tracked = true;
|
132 |
+
__gtagTrackerLog( 'Tracked: ' + valuesArray.type );
|
133 |
+
__gtagTrackerLog( lastClicked );
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* This attempts to be compatible with the gtag function.
|
138 |
+
*
|
139 |
+
* @see https://developers.google.com/analytics/devguides/collection/gtagjs
|
140 |
+
* @param type string Type of request, event, timing, config.
|
141 |
+
* @param action string Event action or UA for config.
|
142 |
+
* @param fieldsArray object The configuration object.
|
143 |
+
* @param valuesArray object The values for the log.
|
144 |
+
* @private
|
145 |
+
*/
|
146 |
+
function __gtagTrackerSend( type, action, fieldsArray, valuesArray ) {
|
147 |
+
type = typeof type !== 'undefined' ? type : 'event';
|
148 |
+
action = typeof action !== 'undefined' ? action : '';
|
149 |
+
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
150 |
+
fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : {};
|
151 |
+
|
152 |
+
__gtagTracker( type, action, fieldsArray );
|
153 |
+
|
154 |
+
lastClicked.valuesArray = valuesArray;
|
155 |
+
lastClicked.fieldsArray = fieldsArray;
|
156 |
+
lastClicked.fieldsArray.event_action = action;
|
157 |
+
lastClicked.tracked = true;
|
158 |
+
__gtagTrackerLog( 'Tracked: ' + valuesArray.type );
|
159 |
+
__gtagTrackerLog( lastClicked );
|
160 |
+
}
|
161 |
+
|
162 |
+
function __gtagTrackerNotSend( valuesArray ) {
|
163 |
+
valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
|
164 |
+
|
165 |
+
lastClicked.valuesArray = valuesArray;
|
166 |
+
lastClicked.fieldsArray = [];
|
167 |
+
lastClicked.tracked = false;
|
168 |
+
__gtagTrackerLog( 'Not Tracked: ' + valuesArray.exit );
|
169 |
+
__gtagTrackerLog( lastClicked );
|
170 |
+
}
|
171 |
+
|
172 |
+
function __gtagTrackerLog( message ) {
|
173 |
+
if ( __gtagTrackerIsDebug() ) {
|
174 |
+
console.dir( message );
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
function __gtagTrackerStringTrim( x ) {
|
179 |
+
return x.replace( /^\s+|\s+$/gm, '' );
|
180 |
+
}
|
181 |
+
|
182 |
+
function __gtagTrackerGetDomain() {
|
183 |
+
var i = 0, currentdomain = document.domain, p = currentdomain.split( '.' ), s = '_gd' + (
|
184 |
+
new Date()
|
185 |
+
).getTime();
|
186 |
+
while ( i < ( p.length - 1 ) && document.cookie.indexOf( s + '=' + s ) == - 1 ) {
|
187 |
+
currentdomain = p.slice( - 1 - (
|
188 |
+
++ i
|
189 |
+
) ).join( '.' );
|
190 |
+
document.cookie = s + "=" + s + ";domain=" + currentdomain + ";";
|
191 |
+
}
|
192 |
+
document.cookie = s + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain=" + currentdomain + ";";
|
193 |
+
return currentdomain;
|
194 |
+
}
|
195 |
+
|
196 |
+
function __gtagTrackerGetExtension( extension ) {
|
197 |
+
extension = extension.toString();
|
198 |
+
extension = extension.substring( 0, (
|
199 |
+
extension.indexOf( "#" ) == - 1
|
200 |
+
) ? extension.length : extension.indexOf( "#" ) ); /* Remove the anchor at the end, if there is one */
|
201 |
+
extension = extension.substring( 0, (
|
202 |
+
extension.indexOf( "?" ) == - 1
|
203 |
+
) ? extension.length : extension.indexOf( "?" ) ); /* Remove the query after the file name, if there is one */
|
204 |
+
extension = extension.substring( extension.lastIndexOf( "/" ) + 1, extension.length ); /* Remove everything before the last slash in the path */
|
205 |
+
if ( extension.length > 0 && extension.indexOf( '.' ) !== - 1 ) { /* If there's a period left in the URL, then there's a extension. Else it is not a extension. */
|
206 |
+
extension = extension.substring( extension.indexOf( "." ) + 1 ); /* Remove everything but what's after the first period */
|
207 |
+
return extension;
|
208 |
+
} else {
|
209 |
+
return "";
|
210 |
+
}
|
211 |
+
}
|
212 |
+
|
213 |
+
function __gtagTrackerTrackedClick( event ) {
|
214 |
+
return event.which == 1 || event.which == 2 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
215 |
+
}
|
216 |
+
|
217 |
+
function __gtagTrackerGetDownloadExtensions() {
|
218 |
+
var download_extensions = [];
|
219 |
+
if ( typeof exactmetrics_frontend.download_extensions == 'string' ) {
|
220 |
+
download_extensions = exactmetrics_frontend.download_extensions.split( "," );
|
221 |
+
}
|
222 |
+
return download_extensions;
|
223 |
+
}
|
224 |
+
|
225 |
+
function __gtagTrackerGetInboundPaths() {
|
226 |
+
var inbound_paths = [];
|
227 |
+
if ( typeof exactmetrics_frontend.inbound_paths == 'string' ) {
|
228 |
+
inbound_paths = JSON.parse( exactmetrics_frontend.inbound_paths );
|
229 |
+
}
|
230 |
+
|
231 |
+
return inbound_paths;
|
232 |
+
}
|
233 |
+
|
234 |
+
function __gtagTrackerTrackedClickType( event ) {
|
235 |
+
if ( event.which == 1 ) {
|
236 |
+
return 'event.which=1';
|
237 |
+
} else if ( event.which == 2 ) {
|
238 |
+
return 'event.which=2';
|
239 |
+
} else if ( event.metaKey ) {
|
240 |
+
return 'metaKey';
|
241 |
+
} else if ( event.ctrlKey ) {
|
242 |
+
return 'ctrlKey';
|
243 |
+
} else if ( event.shiftKey ) {
|
244 |
+
return 'shiftKey';
|
245 |
+
} else if ( event.altKey ) {
|
246 |
+
return 'altKey';
|
247 |
+
} else {
|
248 |
+
return '';
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
function __gtagTrackerLinkType( el ) {
|
253 |
+
var download_extensions = __gtagTrackerGetDownloadExtensions();
|
254 |
+
var inbound_paths = __gtagTrackerGetInboundPaths();
|
255 |
+
var type = 'unknown';
|
256 |
+
var link = el.href;
|
257 |
+
var extension = __gtagTrackerGetExtension( el.href );
|
258 |
+
var currentdomain = __gtagTrackerGetDomain();
|
259 |
+
var hostname = el.hostname;
|
260 |
+
var protocol = el.protocol;
|
261 |
+
var pathname = el.pathname;
|
262 |
+
link = link.toString();
|
263 |
+
var index, len;
|
264 |
+
var category = el.getAttribute( "data-vars-ga-category" );
|
265 |
+
|
266 |
+
if ( category ) {
|
267 |
+
return category;
|
268 |
+
}
|
269 |
+
|
270 |
+
if ( link.match( /^javascript\:/i ) ) {
|
271 |
+
type = 'internal'; /* if it's a JS link, it's internal */
|
272 |
+
} else if ( protocol && protocol.length > 0 && (
|
273 |
+
__gtagTrackerStringTrim( protocol ) == 'tel' || __gtagTrackerStringTrim( protocol ) == 'tel:'
|
274 |
+
) ) { /* If it's a telephone link */
|
275 |
+
type = "tel";
|
276 |
+
} else if ( protocol && protocol.length > 0 && (
|
277 |
+
__gtagTrackerStringTrim( protocol ) == 'mailto' || __gtagTrackerStringTrim( protocol ) == 'mailto:'
|
278 |
+
) ) { /* If it's a email */
|
279 |
+
type = "mailto";
|
280 |
+
} else if ( hostname && currentdomain && hostname.length > 0 && currentdomain.length > 0 && !hostname.endsWith( '.' + currentdomain ) && hostname !== currentdomain ) { /* If it's a outbound */
|
281 |
+
type = "external";
|
282 |
+
} else if ( pathname && JSON.stringify( inbound_paths ) != "{}" && pathname.length > 0 ) { /* If it's an internal as outbound */
|
283 |
+
var inbound_paths_length = inbound_paths.length;
|
284 |
+
for ( var inbound_paths_index = 0; inbound_paths_index < inbound_paths_length; inbound_paths_index ++ ) {
|
285 |
+
if ( inbound_paths[inbound_paths_index].path && inbound_paths[inbound_paths_index].label && inbound_paths[inbound_paths_index].path.length > 0 && inbound_paths[inbound_paths_index].label.length > 0 && pathname.startsWith( inbound_paths[inbound_paths_index].path ) ) {
|
286 |
+
type = "internal-as-outbound";
|
287 |
+
internalAsOutboundCategory = "outbound-link-" + inbound_paths[inbound_paths_index].label;
|
288 |
+
break;
|
289 |
+
}
|
290 |
+
}
|
291 |
+
/* Enable window.exactmetrics_experimental_mode at your own risk. We might eventually remove it. Also you may/can/will burn through GA quota for your property quickly. */
|
292 |
+
} else if ( hostname && window.exactmetrics_experimental_mode && hostname.length > 0 && document.domain.length > 0 && hostname !== document.domain ) { /* If it's a cross-hostname link */
|
293 |
+
type = "cross-hostname";
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( extension && (
|
297 |
+
type === 'unknown' || 'external' === type
|
298 |
+
) && download_extensions.length > 0 && extension.length > 0 ) { /* If it's a download */
|
299 |
+
for ( index = 0, len = download_extensions.length; index < len; ++ index ) {
|
300 |
+
if ( download_extensions[index].length > 0 && (
|
301 |
+
link.endsWith( download_extensions[index] ) || download_extensions[index] == extension
|
302 |
+
) ) {
|
303 |
+
type = "download";
|
304 |
+
break;
|
305 |
+
}
|
306 |
+
}
|
307 |
+
}
|
308 |
+
|
309 |
+
if ( type === 'unknown' ) {
|
310 |
+
type = 'internal';
|
311 |
+
}
|
312 |
+
return type;
|
313 |
+
}
|
314 |
+
|
315 |
+
function __gtagTrackerLinkTarget( el, event ) {
|
316 |
+
|
317 |
+
/* Is actual target set and not _(self|parent|top)? */
|
318 |
+
var target = (
|
319 |
+
el.target && !el.target.match( /^_(self|parent|top)$/i )
|
320 |
+
) ? el.target : false;
|
321 |
+
|
322 |
+
/* Assume a target if Ctrl|shift|meta-click */
|
323 |
+
if ( event.ctrlKey || event.shiftKey || event.metaKey || event.which == 2 ) {
|
324 |
+
target = "_blank";
|
325 |
+
}
|
326 |
+
return target;
|
327 |
+
}
|
328 |
+
|
329 |
+
function __gtagTrackerGetTitle( el ) {
|
330 |
+
if ( el.getAttribute( "data-vars-ga-label" ) && el.getAttribute( "data-vars-ga-label" ).replace( /\n/ig, '' ) ) {
|
331 |
+
return el.getAttribute( "data-vars-ga-label" ).replace( /\n/ig, '' );
|
332 |
+
} else if ( el.title && el.title.replace( /\n/ig, '' ) ) {
|
333 |
+
return el.title.replace( /\n/ig, '' );
|
334 |
+
} else if ( el.innerText && el.innerText.replace( /\n/ig, '' ) ) {
|
335 |
+
return el.innerText.replace( /\n/ig, '' );
|
336 |
+
} else if ( el.getAttribute( 'aria-label' ) && el.getAttribute( 'aria-label' ).replace( /\n/ig, '' ) ) {
|
337 |
+
return el.getAttribute( 'aria-label' ).replace( /\n/ig, '' );
|
338 |
+
} else if ( el.alt && el.alt.replace( /\n/ig, '' ) ) {
|
339 |
+
return el.alt.replace( /\n/ig, '' );
|
340 |
+
} else if ( el.textContent && el.textContent.replace( /\n/ig, '' ) ) {
|
341 |
+
return el.textContent.replace( /\n/ig, '' );
|
342 |
+
} else {
|
343 |
+
return undefined;
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
function __gtagTrackerGetInnerTitle( el ) {
|
348 |
+
var children = el.children;
|
349 |
+
var count = 0;
|
350 |
+
var child;
|
351 |
+
var value;
|
352 |
+
for ( var i = 0; i < children.length; i ++ ) {
|
353 |
+
child = children[i];
|
354 |
+
value = __gtagTrackerGetTitle( child );
|
355 |
+
if ( value ) {
|
356 |
+
return value;
|
357 |
+
}
|
358 |
+
/* max search 100 elements to ensure performance */
|
359 |
+
if ( count == 99 ) {
|
360 |
+
return undefined;
|
361 |
+
}
|
362 |
+
count ++;
|
363 |
+
}
|
364 |
+
return undefined;
|
365 |
+
}
|
366 |
+
|
367 |
+
function __gtagTrackerClickEvent( event ) {
|
368 |
+
var el = event.srcElement || event.target;
|
369 |
+
var valuesArray = [];
|
370 |
+
var fieldsArray;
|
371 |
+
|
372 |
+
/* Start Values Array */
|
373 |
+
valuesArray.el = el;
|
374 |
+
valuesArray.click_type = __gtagTrackerTrackedClickType( event );
|
375 |
+
|
376 |
+
/* If GA is blocked or not loaded, or not main|middle|touch click then don't track */
|
377 |
+
if ( 'undefined' === typeof __gtagTracker || ! __gtagTrackerTrackedClick( event ) ) {
|
378 |
+
valuesArray.exit = 'loaded';
|
379 |
+
__gtagTrackerNotSend( valuesArray );
|
380 |
+
return;
|
381 |
+
}
|
382 |
+
|
383 |
+
/* Loop up the DOM tree through parent elements if clicked element is not a link (eg: an image inside a link) */
|
384 |
+
while ( el && (
|
385 |
+
typeof el.tagName == 'undefined' || el.tagName.toLowerCase() != 'a' || !el.href
|
386 |
+
) ) {
|
387 |
+
el = el.parentNode;
|
388 |
+
}
|
389 |
+
|
390 |
+
/* if a link with valid href has been clicked */
|
391 |
+
if ( el && el.href && !el.hasAttribute( 'xlink:href' ) ) {
|
392 |
+
var link = el.href; /* What link are we tracking */
|
393 |
+
var extension = __gtagTrackerGetExtension( el.href ); /* What extension is this link */
|
394 |
+
var download_extensions = __gtagTrackerGetDownloadExtensions(); /* Let's get the extensions to track */
|
395 |
+
var inbound_paths = __gtagTrackerGetInboundPaths(); /* Let's get the internal paths to track */
|
396 |
+
var home_url = exactmetrics_frontend.home_url; /* Let's get the url to compare for external/internal use */
|
397 |
+
var currentdomain = __gtagTrackerGetDomain(); /* What domain are we on? */
|
398 |
+
var type = __gtagTrackerLinkType( el ); /* What type of link is this? */
|
399 |
+
var target = __gtagTrackerLinkTarget( el, event ); /* Is a new tab/window being opened? */
|
400 |
+
var action = el.getAttribute( "data-vars-ga-action" );
|
401 |
+
var label = el.getAttribute( "data-vars-ga-label" );
|
402 |
+
|
403 |
+
/* Element */
|
404 |
+
valuesArray.el = el; /* el is an a element so we can parse it */
|
405 |
+
valuesArray.el_href = el.href; /* "http://example.com:3000/pathname/?search=test#hash" */
|
406 |
+
valuesArray.el_protocol = el.protocol; /* "http:" */
|
407 |
+
valuesArray.el_hostname = el.hostname; /* "example.com" */
|
408 |
+
valuesArray.el_port = el.port; /* "3000" */
|
409 |
+
valuesArray.el_pathname = el.pathname; /* "/pathname/" */
|
410 |
+
valuesArray.el_search = el.search; /* "?search=test" */
|
411 |
+
valuesArray.el_hash = el.hash; /* "#hash" */
|
412 |
+
valuesArray.el_host = el.host; /* "example.com:3000" */
|
413 |
+
valuesArray.el_classes = el.getAttribute('class')
|
414 |
+
valuesArray.el_id = el.id
|
415 |
+
|
416 |
+
/* Settings */
|
417 |
+
valuesArray.debug_mode = __gtagTrackerIsDebug(); /* "example.com:3000" */
|
418 |
+
valuesArray.download_extensions = download_extensions; /* Let's get the extensions to track */
|
419 |
+
valuesArray.inbound_paths = inbound_paths; /* Let's get the internal paths to track */
|
420 |
+
valuesArray.home_url = home_url; /* Let's get the url to compare for external/internal use */
|
421 |
+
|
422 |
+
/* Parsed/Logic */
|
423 |
+
valuesArray.link = link; /* What link are we tracking */
|
424 |
+
valuesArray.extension = extension; /* What extension is this link */
|
425 |
+
valuesArray.type = type; /* What type of link is this */
|
426 |
+
valuesArray.target = target; /* Is a new tab/window being opened? */
|
427 |
+
valuesArray.title = __gtagTrackerGetTitle( el ); /* Try link title, then text content */
|
428 |
+
|
429 |
+
/* only find innerTitle if we need one */
|
430 |
+
if ( ! valuesArray.label && !valuesArray.title ) {
|
431 |
+
valuesArray.title = __gtagTrackerGetInnerTitle( el );
|
432 |
+
}
|
433 |
+
|
434 |
+
/* Let's track everything but internals (that aren't internal-as-externals) and javascript */
|
435 |
+
if ( type !== 'internal' && type !== 'javascript' ) {
|
436 |
+
|
437 |
+
var __gtagTrackerHitBackRun = false; /* Tracker has not yet run */
|
438 |
+
|
439 |
+
/* HitCallback to open link in same window after tracker */
|
440 |
+
var __gtagTrackerHitBack = function () {
|
441 |
+
/* Run the hitback only once */
|
442 |
+
if ( __gtagTrackerHitBackRun ) {
|
443 |
+
return;
|
444 |
+
}
|
445 |
+
maybePreventBeforeUnload();
|
446 |
+
__gtagTrackerHitBackRun = true;
|
447 |
+
window.location.href = link;
|
448 |
+
};
|
449 |
+
|
450 |
+
var __gtagTrackerNoRedirectExternal = function () {
|
451 |
+
valuesArray.exit = 'external';
|
452 |
+
__gtagTrackerNotSend( valuesArray );
|
453 |
+
};
|
454 |
+
|
455 |
+
var __gtagTrackerNoRedirectInboundAsExternal = function () {
|
456 |
+
valuesArray.exit = 'internal-as-outbound';
|
457 |
+
__gtagTrackerNotSend( valuesArray );
|
458 |
+
};
|
459 |
+
var __gtagTrackerNoRedirectCrossHostname = function () {
|
460 |
+
valuesArray.exit = 'cross-hostname';
|
461 |
+
__gtagTrackerNotSend( valuesArray );
|
462 |
+
};
|
463 |
+
|
464 |
+
if ( target || type == 'mailto' || type == 'tel' ) { /* If target opens a new window then just track */
|
465 |
+
if ( type == 'download' ) {
|
466 |
+
fieldsArray = {
|
467 |
+
event_category: 'download',
|
468 |
+
event_label: label || valuesArray.title,
|
469 |
+
file_extension: valuesArray.extension,
|
470 |
+
file_name: valuesArray.link.replace(/^.*\//g, ''),
|
471 |
+
link_text: label || valuesArray.title,
|
472 |
+
link_url: link,
|
473 |
+
link_domain: valuesArray.el_hostname,
|
474 |
+
link_classes: valuesArray.el_classes,
|
475 |
+
link_id: valuesArray.el_id,
|
476 |
+
};
|
477 |
+
} else if ( type == 'tel' ) {
|
478 |
+
fieldsArray = {
|
479 |
+
event_category: 'tel',
|
480 |
+
event_label: label || valuesArray.title.replace( 'tel:', '' ),
|
481 |
+
tel_number: link.replace( 'tel:', '' ),
|
482 |
+
link_text: label || valuesArray.title,
|
483 |
+
link_url: link,
|
484 |
+
link_classes: valuesArray.el_classes,
|
485 |
+
link_id: valuesArray.el_id,
|
486 |
+
};
|
487 |
+
} else if ( type == 'mailto' ) {
|
488 |
+
fieldsArray = {
|
489 |
+
event_category: 'mailto',
|
490 |
+
event_label: label || valuesArray.title.replace( 'mailto:', '' ),
|
491 |
+
email_address: link.replace( 'mailto:', '' ),
|
492 |
+
link_text: label || valuesArray.title.replace( 'mailto:', ''),
|
493 |
+
link_url: link,
|
494 |
+
link_classes: valuesArray.el_classes,
|
495 |
+
link_id: valuesArray.el_id,
|
496 |
+
};
|
497 |
+
} else if ( type == 'internal-as-outbound' ) {
|
498 |
+
fieldsArray = {
|
499 |
+
event_category: internalAsOutboundCategory,
|
500 |
+
event_label: label || valuesArray.title,
|
501 |
+
event_name: 'click',
|
502 |
+
is_affiliate_link: true,
|
503 |
+
affiliate_label: internalAsOutboundCategory.replace('outbound-link-', ''),
|
504 |
+
link_text: label || valuesArray.title,
|
505 |
+
link_url: link,
|
506 |
+
link_domain: valuesArray.el_hostname,
|
507 |
+
link_classes: valuesArray.el_classes,
|
508 |
+
link_id: valuesArray.el_id,
|
509 |
+
outbound: true,
|
510 |
+
};
|
511 |
+
} else if ( type == 'external' ) {
|
512 |
+
fieldsArray = {
|
513 |
+
event_category: 'outbound-link',
|
514 |
+
event_label: label || valuesArray.title,
|
515 |
+
is_affiliate_link: false,
|
516 |
+
link_text: label || valuesArray.title,
|
517 |
+
link_url: link,
|
518 |
+
link_domain: valuesArray.el_hostname,
|
519 |
+
link_classes: valuesArray.el_classes,
|
520 |
+
link_id: valuesArray.el_id,
|
521 |
+
outbound: true,
|
522 |
+
};
|
523 |
+
} else if ( type == 'cross-hostname' ) {
|
524 |
+
fieldsArray = {
|
525 |
+
event_category: 'cross-hostname',
|
526 |
+
event_label: label || valuesArray.title,
|
527 |
+
link_text: label || valuesArray.title,
|
528 |
+
link_url: link,
|
529 |
+
link_domain: valuesArray.el_hostname,
|
530 |
+
link_classes: valuesArray.el_classes,
|
531 |
+
link_id: valuesArray.el_id,
|
532 |
+
};
|
533 |
+
}
|
534 |
+
|
535 |
+
if ( fieldsArray ) {
|
536 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
537 |
+
} else {
|
538 |
+
if ( type && type != 'internal' ) {
|
539 |
+
fieldsArray = {
|
540 |
+
event_category: type,
|
541 |
+
event_label: label || valuesArray.title,
|
542 |
+
link_text: label || valuesArray.title,
|
543 |
+
link_url: link,
|
544 |
+
link_domain: valuesArray.el_hostname,
|
545 |
+
link_classes: valuesArray.el_classes,
|
546 |
+
link_id: valuesArray.el_id,
|
547 |
+
};
|
548 |
+
|
549 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
550 |
+
} else {
|
551 |
+
valuesArray.exit = 'type';
|
552 |
+
__gtagTrackerNotSend( valuesArray );
|
553 |
+
}
|
554 |
+
}
|
555 |
+
} else {
|
556 |
+
/* Prevent standard click, track then open */
|
557 |
+
if ( type != 'cross-hostname' && type != 'external' && type != 'internal-as-outbound' ) {
|
558 |
+
if ( !event.defaultPrevented ) {
|
559 |
+
if ( event.preventDefault ) {
|
560 |
+
event.preventDefault();
|
561 |
+
} else {
|
562 |
+
event.returnValue = false;
|
563 |
+
}
|
564 |
+
}
|
565 |
+
}
|
566 |
+
|
567 |
+
if ( type == 'download' ) {
|
568 |
+
fieldsArray = {
|
569 |
+
event_category: 'download',
|
570 |
+
event_label: label || valuesArray.title,
|
571 |
+
event_callback: __gtagTrackerHitBack,
|
572 |
+
file_extension: valuesArray.extension,
|
573 |
+
file_name: valuesArray.link.replace(/^.*\//g, ''),
|
574 |
+
link_text: label || valuesArray.title,
|
575 |
+
link_url: link,
|
576 |
+
link_domain: valuesArray.el_hostname,
|
577 |
+
link_classes: valuesArray.el_classes,
|
578 |
+
link_id: valuesArray.el_id,
|
579 |
+
};
|
580 |
+
|
581 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
582 |
+
} else if ( type == 'internal-as-outbound' ) {
|
583 |
+
beforeUnloadChanged = true;
|
584 |
+
window.onbeforeunload = function ( e ) {
|
585 |
+
if ( !event.defaultPrevented ) {
|
586 |
+
if ( event.preventDefault ) {
|
587 |
+
event.preventDefault();
|
588 |
+
} else {
|
589 |
+
event.returnValue = false;
|
590 |
+
}
|
591 |
+
}
|
592 |
+
|
593 |
+
fieldsArray = {
|
594 |
+
event_category: internalAsOutboundCategory,
|
595 |
+
event_label: label || valuesArray.title,
|
596 |
+
event_callback: __gtagTrackerHitBack,
|
597 |
+
is_affiliate_link: true,
|
598 |
+
affiliate_label: internalAsOutboundCategory.replace('outbound-link-', ''),
|
599 |
+
link_text: label || valuesArray.title,
|
600 |
+
link_url: link,
|
601 |
+
link_domain: valuesArray.el_hostname,
|
602 |
+
link_classes: valuesArray.el_classes,
|
603 |
+
link_id: valuesArray.el_id,
|
604 |
+
outbound: true,
|
605 |
+
};
|
606 |
+
|
607 |
+
if ( navigator.sendBeacon ) {
|
608 |
+
fieldsArray.transport = 'beacon';
|
609 |
+
}
|
610 |
+
|
611 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
612 |
+
|
613 |
+
setTimeout( __gtagTrackerHitBack, 1000 );
|
614 |
+
};
|
615 |
+
} else if ( type == 'external' ) {
|
616 |
+
beforeUnloadChanged = true;
|
617 |
+
window.onbeforeunload = function ( e ) {
|
618 |
+
if ( !event.defaultPrevented ) {
|
619 |
+
if ( event.preventDefault ) {
|
620 |
+
event.preventDefault();
|
621 |
+
} else {
|
622 |
+
event.returnValue = false;
|
623 |
+
}
|
624 |
+
}
|
625 |
+
|
626 |
+
fieldsArray = {
|
627 |
+
event_category: 'outbound-link',
|
628 |
+
event_label: label || valuesArray.title,
|
629 |
+
event_callback: __gtagTrackerHitBack,
|
630 |
+
is_affiliate_link: false,
|
631 |
+
link_text: label || valuesArray.title,
|
632 |
+
link_url: link,
|
633 |
+
link_domain: valuesArray.el_hostname,
|
634 |
+
link_classes: valuesArray.el_classes,
|
635 |
+
link_id: valuesArray.el_id,
|
636 |
+
outbound: true,
|
637 |
+
};
|
638 |
+
|
639 |
+
if ( navigator.sendBeacon ) {
|
640 |
+
fieldsArray.transport = 'beacon';
|
641 |
+
}
|
642 |
+
|
643 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
644 |
+
setTimeout( __gtagTrackerHitBack, 1000 );
|
645 |
+
};
|
646 |
+
} else if ( type == 'cross-hostname' ) {
|
647 |
+
beforeUnloadChanged = true;
|
648 |
+
window.onbeforeunload = function ( e ) {
|
649 |
+
if ( !event.defaultPrevented ) {
|
650 |
+
if ( event.preventDefault ) {
|
651 |
+
event.preventDefault();
|
652 |
+
} else {
|
653 |
+
event.returnValue = false;
|
654 |
+
}
|
655 |
+
}
|
656 |
+
|
657 |
+
fieldsArray = {
|
658 |
+
event_category: 'cross-hostname',
|
659 |
+
event_label: label || valuesArray.title,
|
660 |
+
event_callback: __gtagTrackerHitBack,
|
661 |
+
link_text: label || valuesArray.title,
|
662 |
+
link_url: link,
|
663 |
+
link_domain: valuesArray.el_hostname,
|
664 |
+
link_classes: valuesArray.el_classes,
|
665 |
+
link_id: valuesArray.el_id,
|
666 |
+
};
|
667 |
+
|
668 |
+
if ( navigator.sendBeacon ) {
|
669 |
+
fieldsArray.transport = 'beacon';
|
670 |
+
}
|
671 |
+
|
672 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
673 |
+
setTimeout( __gtagTrackerHitBack, 1000 );
|
674 |
+
};
|
675 |
+
} else {
|
676 |
+
if ( type && type !== 'internal' ) {
|
677 |
+
fieldsArray = {
|
678 |
+
event_category: type,
|
679 |
+
event_label: label || valuesArray.title,
|
680 |
+
event_callback: __gtagTrackerHitBack,
|
681 |
+
link_text: label || valuesArray.title,
|
682 |
+
link_url: link,
|
683 |
+
link_domain: valuesArray.el_hostname,
|
684 |
+
link_classes: valuesArray.el_classes,
|
685 |
+
link_id: valuesArray.el_id,
|
686 |
+
};
|
687 |
+
|
688 |
+
__gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
|
689 |
+
} else {
|
690 |
+
valuesArray.exit = 'type';
|
691 |
+
__gtagTrackerNotSend( valuesArray );
|
692 |
+
}
|
693 |
+
}
|
694 |
+
|
695 |
+
if ( type != 'external' && type != 'cross-hostname' && type != 'internal-as-outbound' ) {
|
696 |
+
/* Run event_callback again if GA takes longer than 1 second */
|
697 |
+
setTimeout( __gtagTrackerHitBack, 1000 );
|
698 |
+
} else {
|
699 |
+
if ( type == 'external' ) {
|
700 |
+
setTimeout( __gtagTrackerNoRedirectExternal, 1100 );
|
701 |
+
} else if ( type == 'cross-hostname' ) {
|
702 |
+
setTimeout( __gtagTrackerNoRedirectCrossHostname, 1100 );
|
703 |
+
} else {
|
704 |
+
setTimeout( __gtagTrackerNoRedirectInboundAsExternal, 1100 );
|
705 |
+
}
|
706 |
+
}
|
707 |
+
|
708 |
+
// Clear out the beforeunload event if it was set to avoid sending false events.
|
709 |
+
setTimeout( maybePreventBeforeUnload, 100 );
|
710 |
+
}
|
711 |
+
} else {
|
712 |
+
maybePreventBeforeUnload();
|
713 |
+
valuesArray.exit = 'internal';
|
714 |
+
__gtagTrackerNotSend( valuesArray );
|
715 |
+
}
|
716 |
+
} else {
|
717 |
+
valuesArray.exit = 'notlink';
|
718 |
+
__gtagTrackerNotSend( valuesArray );
|
719 |
+
}
|
720 |
+
}
|
721 |
+
|
722 |
+
var prevHash = window.location.hash;
|
723 |
+
|
724 |
+
function __gtagTrackerHashChangeEvent() {
|
725 |
+
/* Todo: Ready this section for JS unit testing */
|
726 |
+
if ( exactmetrics_frontend.hash_tracking === "true" && prevHash != window.location.hash && ( exactmetrics_frontend.ua || exactmetrics_frontend.v4_id ) ) {
|
727 |
+
prevHash = window.location.hash;
|
728 |
+
if ( exactmetrics_frontend.ua ) {
|
729 |
+
__gtagTracker( 'config', exactmetrics_frontend.ua, {
|
730 |
+
page_path: location.pathname + location.search + location.hash,
|
731 |
+
} );
|
732 |
+
}
|
733 |
+
|
734 |
+
if ( exactmetrics_frontend.v4_id ) {
|
735 |
+
__gtagTracker( 'config', exactmetrics_frontend.v4_id, {
|
736 |
+
page_path: location.pathname + location.search + location.hash,
|
737 |
+
} );
|
738 |
+
}
|
739 |
+
__gtagTrackerLog( "Hash change to: " + location.pathname + location.search + location.hash );
|
740 |
+
} else {
|
741 |
+
__gtagTrackerLog( "Hash change to (untracked): " + location.pathname + location.search + location.hash );
|
742 |
+
}
|
743 |
+
}
|
744 |
+
|
745 |
+
function maybePreventBeforeUnload() {
|
746 |
+
if ( beforeUnloadChanged ) {
|
747 |
+
window.onbeforeunload = null;
|
748 |
+
}
|
749 |
+
}
|
750 |
+
|
751 |
+
/* Attach the event to all clicks in the document after page has loaded */
|
752 |
+
var __gtagTrackerWindow = window;
|
753 |
+
if ( __gtagTrackerWindow.addEventListener ) {
|
754 |
+
__gtagTrackerWindow.addEventListener(
|
755 |
+
"load",
|
756 |
+
function () {
|
757 |
+
document.body.addEventListener(
|
758 |
+
"click",
|
759 |
+
__gtagTrackerClickEvent,
|
760 |
+
false
|
761 |
+
);
|
762 |
+
},
|
763 |
+
false
|
764 |
+
);
|
765 |
+
window.addEventListener( "hashchange", __gtagTrackerHashChangeEvent, false );
|
766 |
+
} else {
|
767 |
+
if ( __gtagTrackerWindow.attachEvent ) {
|
768 |
+
__gtagTrackerWindow.attachEvent(
|
769 |
+
"onload",
|
770 |
+
function () {
|
771 |
+
document.body.attachEvent( "onclick", __gtagTrackerClickEvent );
|
772 |
+
}
|
773 |
+
);
|
774 |
+
window.attachEvent( "onhashchange", __gtagTrackerHashChangeEvent );
|
775 |
+
}
|
776 |
+
}
|
777 |
+
|
778 |
+
if ( typeof String.prototype.endsWith !== 'function' ) {
|
779 |
+
String.prototype.endsWith = function ( suffix ) {
|
780 |
+
return this.indexOf( suffix, this.length - suffix.length ) !== - 1;
|
781 |
+
};
|
782 |
+
}
|
783 |
+
if ( typeof String.prototype.startsWith !== 'function' ) {
|
784 |
+
String.prototype.startsWith = function ( prefix ) {
|
785 |
+
return this.indexOf( prefix ) === 0;
|
786 |
+
};
|
787 |
+
}
|
788 |
+
|
789 |
+
if ( typeof Array.prototype.lastIndexOf !== 'function' ) {
|
790 |
+
Array.prototype.lastIndexOf = function ( searchElement /*, fromIndex*/ ) {
|
791 |
+
'use strict';
|
792 |
+
|
793 |
+
if ( this === void 0 || this === null ) {
|
794 |
+
throw new TypeError();
|
795 |
+
}
|
796 |
+
|
797 |
+
var n, k,
|
798 |
+
t = Object( this ),
|
799 |
+
len = t.length >>> 0; /* jshint ignore:line */
|
800 |
+
if ( len === 0 ) {
|
801 |
+
return - 1;
|
802 |
+
}
|
803 |
+
|
804 |
+
n = len - 1;
|
805 |
+
if ( arguments.length > 1 ) {
|
806 |
+
n = Number( arguments[1] );
|
807 |
+
if ( n != n ) {
|
808 |
+
n = 0;
|
809 |
+
} else if ( n != 0 && n != (
|
810 |
+
1 / 0
|
811 |
+
) && n != - (
|
812 |
+
1 / 0
|
813 |
+
) ) { /* jshint ignore:line */
|
814 |
+
n = (
|
815 |
+
n > 0 || - 1
|
816 |
+
) * Math.floor( Math.abs( n ) );
|
817 |
+
}
|
818 |
+
}
|
819 |
+
|
820 |
+
for ( k = n >= 0 ? Math.min( n, len - 1 ) : len - Math.abs( n ); k >= 0; k -- ) {
|
821 |
+
if ( k in t && t[k] === searchElement ) {
|
822 |
+
return k;
|
823 |
+
}
|
824 |
+
}
|
825 |
+
return - 1;
|
826 |
+
};
|
827 |
+
}
|
828 |
+
};
|
829 |
+
var ExactMetricsObject = new ExactMetrics();
|
assets/js/popular-posts.js
CHANGED
@@ -1,33 +1,33 @@
|
|
1 |
-
var ExactMetrics_Popular_Posts = {
|
2 |
-
|
3 |
-
init: function () {
|
4 |
-
this.grab_widgets_with_ajax();
|
5 |
-
},
|
6 |
-
|
7 |
-
grab_widgets_with_ajax: function () {
|
8 |
-
var xhr = new XMLHttpRequest();
|
9 |
-
var url = exactmetrics_pp.ajaxurl;
|
10 |
-
var widgets_jsons = document.querySelectorAll( '.exactmetrics-popular-posts-widget-json' ),
|
11 |
-
i,
|
12 |
-
widgets_length = widgets_jsons.length;
|
13 |
-
|
14 |
-
var params = 'action=exactmetrics_popular_posts_get_widget_output&post_id=' + exactmetrics_pp.post_id;
|
15 |
-
|
16 |
-
for ( i = 0; i < widgets_length; ++ i ) {
|
17 |
-
params += '&data[]=' + widgets_jsons[i].innerHTML
|
18 |
-
}
|
19 |
-
xhr.open( 'POST', url );
|
20 |
-
xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
|
21 |
-
xhr.onload = function () {
|
22 |
-
if ( xhr.status === 200 ) {
|
23 |
-
let rendered_widgets = JSON.parse( xhr.responseText );
|
24 |
-
for ( i = 0; i < widgets_length; ++ i ) {
|
25 |
-
widgets_jsons[i].parentElement.innerHTML = rendered_widgets[i];
|
26 |
-
}
|
27 |
-
}
|
28 |
-
};
|
29 |
-
xhr.send( params );
|
30 |
-
},
|
31 |
-
};
|
32 |
-
|
33 |
-
ExactMetrics_Popular_Posts.init();
|
1 |
+
var ExactMetrics_Popular_Posts = {
|
2 |
+
|
3 |
+
init: function () {
|
4 |
+
this.grab_widgets_with_ajax();
|
5 |
+
},
|
6 |
+
|
7 |
+
grab_widgets_with_ajax: function () {
|
8 |
+
var xhr = new XMLHttpRequest();
|
9 |
+
var url = exactmetrics_pp.ajaxurl;
|
10 |
+
var widgets_jsons = document.querySelectorAll( '.exactmetrics-popular-posts-widget-json' ),
|
11 |
+
i,
|
12 |
+
widgets_length = widgets_jsons.length;
|
13 |
+
|
14 |
+
var params = 'action=exactmetrics_popular_posts_get_widget_output&post_id=' + exactmetrics_pp.post_id;
|
15 |
+
|
16 |
+
for ( i = 0; i < widgets_length; ++ i ) {
|
17 |
+
params += '&data[]=' + widgets_jsons[i].innerHTML
|
18 |
+
}
|
19 |
+
xhr.open( 'POST', url );
|
20 |
+
xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
|
21 |
+
xhr.onload = function () {
|
22 |
+
if ( xhr.status === 200 ) {
|
23 |
+
let rendered_widgets = JSON.parse( xhr.responseText );
|
24 |
+
for ( i = 0; i < widgets_length; ++ i ) {
|
25 |
+
widgets_jsons[i].parentElement.innerHTML = rendered_widgets[i];
|
26 |
+
}
|
27 |
+
}
|
28 |
+
};
|
29 |
+
xhr.send( params );
|
30 |
+
},
|
31 |
+
};
|
32 |
+
|
33 |
+
ExactMetrics_Popular_Posts.init();
|
gadwp.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
* Plugin URI: https://exactmetrics.com
|
5 |
* Description: Displays Google Analytics Reports and Real-Time Statistics in your Dashboard. Automatically inserts the tracking code in every page of your website.
|
6 |
* Author: ExactMetrics
|
7 |
-
* Version: 7.2.
|
8 |
* Requires at least: 4.8.0
|
9 |
* Requires PHP: 5.5
|
10 |
* Author URI: https://exactmetrics.com
|
@@ -44,7 +44,7 @@ final class ExactMetrics_Lite {
|
|
44 |
* @access public
|
45 |
* @var string $version Plugin version.
|
46 |
*/
|
47 |
-
public $version = '7.2.
|
48 |
|
49 |
/**
|
50 |
* Plugin file.
|
4 |
* Plugin URI: https://exactmetrics.com
|
5 |
* Description: Displays Google Analytics Reports and Real-Time Statistics in your Dashboard. Automatically inserts the tracking code in every page of your website.
|
6 |
* Author: ExactMetrics
|
7 |
+
* Version: 7.2.0
|
8 |
* Requires at least: 4.8.0
|
9 |
* Requires PHP: 5.5
|
10 |
* Author URI: https://exactmetrics.com
|
44 |
* @access public
|
45 |
* @var string $version Plugin version.
|
46 |
*/
|
47 |
+
public $version = '7.2.0';
|
48 |
|
49 |
/**
|
50 |
* Plugin file.
|
includes/admin/em-admin.php
CHANGED
@@ -1,25 +1,25 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Add menu items in admin bar
|
4 |
-
*
|
5 |
-
* @since 6.6.0
|
6 |
-
*
|
7 |
-
* @param object $wp_admin_bar WP_Admin_Bar instance, passed by reference
|
8 |
-
*/
|
9 |
-
function exactmetrics_admin_bar_items( $admin_bar ) {
|
10 |
-
if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
|
11 |
-
return;
|
12 |
-
}
|
13 |
-
|
14 |
-
$admin_bar->add_menu( array(
|
15 |
-
'id' => 'exactmetrics-analyltics-reports',
|
16 |
-
'parent' => 'wp-logo',
|
17 |
-
'group' => null,
|
18 |
-
'title' => 'ExactMetrics',
|
19 |
-
'href' => add_query_arg( 'page', 'exactmetrics_reports', admin_url( 'admin.php' ) ),
|
20 |
-
'meta' => array(
|
21 |
-
'title' => 'ExactMetrics',
|
22 |
-
),
|
23 |
-
) );
|
24 |
-
}
|
25 |
-
add_action( 'admin_bar_menu', 'exactmetrics_admin_bar_items', 500 );
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Add menu items in admin bar
|
4 |
+
*
|
5 |
+
* @since 6.6.0
|
6 |
+
*
|
7 |
+
* @param object $wp_admin_bar WP_Admin_Bar instance, passed by reference
|
8 |
+
*/
|
9 |
+
function exactmetrics_admin_bar_items( $admin_bar ) {
|
10 |
+
if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
|
11 |
+
return;
|
12 |
+
}
|
13 |
+
|
14 |
+
$admin_bar->add_menu( array(
|
15 |
+
'id' => 'exactmetrics-analyltics-reports',
|
16 |
+
'parent' => 'wp-logo',
|
17 |
+
'group' => null,
|
18 |
+
'title' => 'ExactMetrics',
|
19 |
+
'href' => add_query_arg( 'page', 'exactmetrics_reports', admin_url( 'admin.php' ) ),
|
20 |
+
'meta' => array(
|
21 |
+
'title' => 'ExactMetrics',
|
22 |
+
),
|
23 |
+
) );
|
24 |
+
}
|
25 |
+
add_action( 'admin_bar_menu', 'exactmetrics_admin_bar_items', 500 );
|
includes/admin/notification-event-runner.php
CHANGED
@@ -1,189 +1,189 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Custom runner system for recurring notifications.
|
4 |
-
*
|
5 |
-
* @since 7.14
|
6 |
-
* @author Mircea Sandu
|
7 |
-
* @package ExactMetrics
|
8 |
-
*/
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class ExactMetrics_Notification_Event_Runner
|
12 |
-
*/
|
13 |
-
class ExactMetrics_Notification_Event_Runner {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* The instance of the current class.
|
17 |
-
*
|
18 |
-
* @var ExactMetrics_Notification_Event_Runner
|
19 |
-
*/
|
20 |
-
private static $instance;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* The static notifications registered.
|
24 |
-
*
|
25 |
-
* @var array
|
26 |
-
*/
|
27 |
-
private static $notifications = array();
|
28 |
-
|
29 |
-
/**
|
30 |
-
* The key used to store in the options table the last run times for notifications.
|
31 |
-
*
|
32 |
-
* @var string
|
33 |
-
*/
|
34 |
-
private $last_run_key = 'exactmetrics_notifications_run';
|
35 |
-
|
36 |
-
/**
|
37 |
-
* This will be populated on demand with the last run timestamps for all the notifications.
|
38 |
-
*
|
39 |
-
* @var array|bool
|
40 |
-
*/
|
41 |
-
private $last_run;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Only update the option if something changed.
|
45 |
-
*
|
46 |
-
* @var bool
|
47 |
-
*/
|
48 |
-
private $changed = false;
|
49 |
-
|
50 |
-
/**
|
51 |
-
* ExactMetrics_Notification_Event_Runner constructor.
|
52 |
-
*/
|
53 |
-
private function __construct() {
|
54 |
-
add_action( 'wp_ajax_exactmetrics_vue_get_notifications', array( $this, 'maybe_add_notifications' ), 9 );
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Get the singleton instance.
|
59 |
-
*
|
60 |
-
* @return ExactMetrics_Notification_Event_Runner
|
61 |
-
*/
|
62 |
-
public static function get_instance() {
|
63 |
-
if ( ! isset( self::$instance ) ) {
|
64 |
-
self::$instance = new self();
|
65 |
-
}
|
66 |
-
|
67 |
-
return self::$instance;
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Get the stored option for the last run times.
|
72 |
-
*
|
73 |
-
* @return false|mixed|void
|
74 |
-
*/
|
75 |
-
public function get_notifications_last_run() {
|
76 |
-
if ( ! isset( $this->last_run ) ) {
|
77 |
-
$this->last_run = get_option( $this->last_run_key );
|
78 |
-
}
|
79 |
-
|
80 |
-
return $this->last_run;
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Update the last run time with a default of time.
|
85 |
-
*
|
86 |
-
* @param string $notification_id The notification id to update the last run time for.
|
87 |
-
* @param string|int $time The timestamp to store the last run time.
|
88 |
-
*/
|
89 |
-
public function update_last_run( $notification_id, $time = '' ) {
|
90 |
-
if ( empty( $time ) ) {
|
91 |
-
$time = time();
|
92 |
-
}
|
93 |
-
|
94 |
-
$this->last_run[ $notification_id ] = $time;
|
95 |
-
$this->changed = true;
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Update the option stored in the db with the last run times.
|
100 |
-
*/
|
101 |
-
public function save_last_runs() {
|
102 |
-
if ( $this->changed ) {
|
103 |
-
update_option( $this->last_run_key, $this->last_run, false );
|
104 |
-
}
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Loop through notifications and check if they should be added based on the time passed since they were last added.
|
109 |
-
*/
|
110 |
-
public function maybe_add_notifications() {
|
111 |
-
|
112 |
-
if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
|
113 |
-
// No need to try adding the notification if the user can't see it.
|
114 |
-
return;
|
115 |
-
}
|
116 |
-
|
117 |
-
$notifications = $this->get_registered_notifications();
|
118 |
-
$last_runs = $this->get_notifications_last_run();
|
119 |
-
|
120 |
-
// Loop through registered notifications.
|
121 |
-
foreach ( $notifications as $notification ) {
|
122 |
-
/**¬
|
123 |
-
* The notification instance.
|
124 |
-
*
|
125 |
-
* @var ExactMetrics_Notification_Event $notification
|
126 |
-
*/
|
127 |
-
if ( empty( $last_runs[ $notification->notification_id ] ) ) {
|
128 |
-
// If the notification never ran, save current time to show it after the interval.
|
129 |
-
$this->update_last_run( $notification->notification_id );
|
130 |
-
} else {
|
131 |
-
// Has run before so let's check if enough days passed since the last run.
|
132 |
-
$time_since = $last_runs[ $notification->notification_id ] + $notification->notification_interval * DAY_IN_SECONDS;
|
133 |
-
$time_now = time();
|
134 |
-
if ( $time_since < $time_now ) {
|
135 |
-
// Interval passed since it ran so let's add this one.
|
136 |
-
$notification->add_notification();
|
137 |
-
// Update the last run date as right now.
|
138 |
-
$this->update_last_run( $notification->notification_id );
|
139 |
-
// Let's not add multiple notifications at the same time.
|
140 |
-
break;
|
141 |
-
}
|
142 |
-
}
|
143 |
-
}
|
144 |
-
|
145 |
-
// Update the option with the new times.
|
146 |
-
$this->save_last_runs();
|
147 |
-
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Get the static notifications array.
|
152 |
-
*
|
153 |
-
* @return array
|
154 |
-
*/
|
155 |
-
public function get_registered_notifications() {
|
156 |
-
return self::$notifications;
|
157 |
-
}
|
158 |
-
|
159 |
-
/**
|
160 |
-
* Register the notification for running it later.
|
161 |
-
*
|
162 |
-
* @param ExactMetrics_Notification_Event $notification The instance of the notification.
|
163 |
-
*/
|
164 |
-
public function register_notification( $notification ) {
|
165 |
-
|
166 |
-
$notification_id = isset( $notification->notification_id ) ? $notification->notification_id : false;
|
167 |
-
if ( ! empty( $notification_id ) && ! isset( self::$notifications[ $notification_id ] ) ) {
|
168 |
-
self::$notifications[ $notification_id ] = $notification;
|
169 |
-
}
|
170 |
-
|
171 |
-
}
|
172 |
-
|
173 |
-
/**
|
174 |
-
* Delete the data on uninstall.
|
175 |
-
*/
|
176 |
-
public function delete_data() {
|
177 |
-
delete_option( $this->last_run_key );
|
178 |
-
}
|
179 |
-
|
180 |
-
}
|
181 |
-
|
182 |
-
/**
|
183 |
-
* Get the single instance of the event runner class.
|
184 |
-
*
|
185 |
-
* @return ExactMetrics_Notification_Event_Runner
|
186 |
-
*/
|
187 |
-
function exactmetrics_notification_event_runner() {
|
188 |
-
return ExactMetrics_Notification_Event_Runner::get_instance();
|
189 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Custom runner system for recurring notifications.
|
4 |
+
*
|
5 |
+
* @since 7.14
|
6 |
+
* @author Mircea Sandu
|
7 |
+
* @package ExactMetrics
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class ExactMetrics_Notification_Event_Runner
|
12 |
+
*/
|
13 |
+
class ExactMetrics_Notification_Event_Runner {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The instance of the current class.
|
17 |
+
*
|
18 |
+
* @var ExactMetrics_Notification_Event_Runner
|
19 |
+
*/
|
20 |
+
private static $instance;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* The static notifications registered.
|
24 |
+
*
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
private static $notifications = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* The key used to store in the options table the last run times for notifications.
|
31 |
+
*
|
32 |
+
* @var string
|
33 |
+
*/
|
34 |
+
private $last_run_key = 'exactmetrics_notifications_run';
|
35 |
+
|
36 |
+
/**
|
37 |
+
* This will be populated on demand with the last run timestamps for all the notifications.
|
38 |
+
*
|
39 |
+
* @var array|bool
|
40 |
+
*/
|
41 |
+
private $last_run;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Only update the option if something changed.
|
45 |
+
*
|
46 |
+
* @var bool
|
47 |
+
*/
|
48 |
+
private $changed = false;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* ExactMetrics_Notification_Event_Runner constructor.
|
52 |
+
*/
|
53 |
+
private function __construct() {
|
54 |
+
add_action( 'wp_ajax_exactmetrics_vue_get_notifications', array( $this, 'maybe_add_notifications' ), 9 );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get the singleton instance.
|
59 |
+
*
|
60 |
+
* @return ExactMetrics_Notification_Event_Runner
|
61 |
+
*/
|
62 |
+
public static function get_instance() {
|
63 |
+
if ( ! isset( self::$instance ) ) {
|
64 |
+
self::$instance = new self();
|
65 |
+
}
|
66 |
+
|
67 |
+
return self::$instance;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Get the stored option for the last run times.
|
72 |
+
*
|
73 |
+
* @return false|mixed|void
|
74 |
+
*/
|
75 |
+
public function get_notifications_last_run() {
|
76 |
+
if ( ! isset( $this->last_run ) ) {
|
77 |
+
$this->last_run = get_option( $this->last_run_key );
|
78 |
+
}
|
79 |
+
|
80 |
+
return $this->last_run;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Update the last run time with a default of time.
|
85 |
+
*
|
86 |
+
* @param string $notification_id The notification id to update the last run time for.
|
87 |
+
* @param string|int $time The timestamp to store the last run time.
|
88 |
+
*/
|
89 |
+
public function update_last_run( $notification_id, $time = '' ) {
|
90 |
+
if ( empty( $time ) ) {
|
91 |
+
$time = time();
|
92 |
+
}
|
93 |
+
|
94 |
+
$this->last_run[ $notification_id ] = $time;
|
95 |
+
$this->changed = true;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Update the option stored in the db with the last run times.
|
100 |
+
*/
|
101 |
+
public function save_last_runs() {
|
102 |
+
if ( $this->changed ) {
|
103 |
+
update_option( $this->last_run_key, $this->last_run, false );
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Loop through notifications and check if they should be added based on the time passed since they were last added.
|
109 |
+
*/
|
110 |
+
public function maybe_add_notifications() {
|
111 |
+
|
112 |
+
if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
|
113 |
+
// No need to try adding the notification if the user can't see it.
|
114 |
+
return;
|
115 |
+
}
|
116 |
+
|
117 |
+
$notifications = $this->get_registered_notifications();
|
118 |
+
$last_runs = $this->get_notifications_last_run();
|
119 |
+
|
120 |
+
// Loop through registered notifications.
|
121 |
+
foreach ( $notifications as $notification ) {
|
122 |
+
/**¬
|
123 |
+
* The notification instance.
|
124 |
+
*
|
125 |
+
* @var ExactMetrics_Notification_Event $notification
|
126 |
+
*/
|
127 |
+
if ( empty( $last_runs[ $notification->notification_id ] ) ) {
|
128 |
+
// If the notification never ran, save current time to show it after the interval.
|
129 |
+
$this->update_last_run( $notification->notification_id );
|
130 |
+
} else {
|
131 |
+
// Has run before so let's check if enough days passed since the last run.
|
132 |
+
$time_since = $last_runs[ $notification->notification_id ] + $notification->notification_interval * DAY_IN_SECONDS;
|
133 |
+
$time_now = time();
|
134 |
+
if ( $time_since < $time_now ) {
|
135 |
+
// Interval passed since it ran so let's add this one.
|
136 |
+
$notification->add_notification();
|
137 |
+
// Update the last run date as right now.
|
138 |
+
$this->update_last_run( $notification->notification_id );
|
139 |
+
// Let's not add multiple notifications at the same time.
|
140 |
+
break;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
// Update the option with the new times.
|
146 |
+
$this->save_last_runs();
|
147 |
+
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Get the static notifications array.
|
152 |
+
*
|
153 |
+
* @return array
|
154 |
+
*/
|
155 |
+
public function get_registered_notifications() {
|
156 |
+
return self::$notifications;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Register the notification for running it later.
|
161 |
+
*
|
162 |
+
* @param ExactMetrics_Notification_Event $notification The instance of the notification.
|
163 |
+
*/
|
164 |
+
public function register_notification( $notification ) {
|
165 |
+
|
166 |
+
$notification_id = isset( $notification->notification_id ) ? $notification->notification_id : false;
|
167 |
+
if ( ! empty( $notification_id ) && ! isset( self::$notifications[ $notification_id ] ) ) {
|
168 |
+
self::$notifications[ $notification_id ] = $notification;
|
169 |
+
}
|
170 |
+
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Delete the data on uninstall.
|
175 |
+
*/
|
176 |
+
public function delete_data() {
|
177 |
+
delete_option( $this->last_run_key );
|
178 |
+
}
|
179 |
+
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Get the single instance of the event runner class.
|
184 |
+
*
|
185 |
+
* @return ExactMetrics_Notification_Event_Runner
|
186 |
+
*/
|
187 |
+
function exactmetrics_notification_event_runner() {
|
188 |
+
return ExactMetrics_Notification_Event_Runner::get_instance();
|
189 |
+
}
|
includes/admin/notification-event.php
CHANGED
@@ -1,237 +1,237 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Parent Class for ExactMetrics Notification Event
|
4 |
-
*
|
5 |
-
* @since 7.12.3
|
6 |
-
*
|
7 |
-
* @package ExactMetrics
|
8 |
-
*/
|
9 |
-
|
10 |
-
class ExactMetrics_Notification_Event {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Generate unique notification id
|
14 |
-
*
|
15 |
-
* @var string
|
16 |
-
*
|
17 |
-
* @since 7.12.3
|
18 |
-
*/
|
19 |
-
public $notification_id;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* When the notification will repeat (e.g: 7) here `7` to repeat the notification after each 7 days
|
23 |
-
* Only accept numeric value
|
24 |
-
*
|
25 |
-
* @var number
|
26 |
-
*
|
27 |
-
* @since 7.12.3
|
28 |
-
*/
|
29 |
-
public $notification_interval;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* When the notification will active, default: now
|
33 |
-
*
|
34 |
-
* @var string
|
35 |
-
*
|
36 |
-
* @since 7.12.3
|
37 |
-
*/
|
38 |
-
public $notification_active_from;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* For how many days notification will be active
|
42 |
-
*
|
43 |
-
* @var string
|
44 |
-
*
|
45 |
-
* @since 7.12.3
|
46 |
-
*/
|
47 |
-
public $notification_active_for;
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Which type of license is allowed to view this notification
|
51 |
-
*
|
52 |
-
* @var array
|
53 |
-
*
|
54 |
-
* @since 7.12.3
|
55 |
-
*/
|
56 |
-
public $notification_type;
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Report start date if required e.g: "-15 day"(Readable Time)
|
60 |
-
*
|
61 |
-
* @var string
|
62 |
-
*
|
63 |
-
* @since 7.12.3
|
64 |
-
*/
|
65 |
-
public $report_start_from;
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Report end date if required e.g: "-1 day"(Readable Time)
|
69 |
-
*
|
70 |
-
* @var string
|
71 |
-
*
|
72 |
-
* @since 7.12.3
|
73 |
-
*/
|
74 |
-
public $report_end_to;
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Notification icon to display with content
|
78 |
-
*
|
79 |
-
* @var string
|
80 |
-
*
|
81 |
-
* @since 7.12.3
|
82 |
-
*/
|
83 |
-
public $notification_icon;
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Constructor
|
87 |
-
*
|
88 |
-
* @since 7.12.3
|
89 |
-
*/
|
90 |
-
public function __construct() {
|
91 |
-
|
92 |
-
$this->notification_active_from = date( 'm/d/Y g:i a', strtotime( 'now' ) );
|
93 |
-
$this->report_end_to = '-1 day'; // Yesterday.
|
94 |
-
|
95 |
-
if ( ! empty( $this->notification_id ) && ! empty( $this->notification_interval ) ) {
|
96 |
-
|
97 |
-
// Register notification in our custom runner.
|
98 |
-
exactmetrics_notification_event_runner()->register_notification( $this );
|
99 |
-
|
100 |
-
$this->notification_active_for = date( 'm/d/Y', strtotime( '+' . ( $this->notification_interval - 2 ) . ' day' ) );
|
101 |
-
$this->report_start_from = '-' . $this->notification_interval . ' day';
|
102 |
-
|
103 |
-
if ( ! isset( $this->notification_icon ) || empty( $this->notification_icon ) ) {
|
104 |
-
$this->notification_icon = 'default';
|
105 |
-
}
|
106 |
-
|
107 |
-
}
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* Get the formatted date.
|
112 |
-
*
|
113 |
-
* @param string $readable_time Readable time to convert to date.
|
114 |
-
*
|
115 |
-
* @return string date, format: Y-m-d
|
116 |
-
*
|
117 |
-
* @since 7.12.3
|
118 |
-
*/
|
119 |
-
public function get_formatted_date( $readable_time ) {
|
120 |
-
return date( 'Y-m-d', strtotime( $readable_time ) );
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Get the upgrade URL for pro plugin
|
125 |
-
*
|
126 |
-
* @return string
|
127 |
-
*/
|
128 |
-
public function get_upgrade_url() {
|
129 |
-
return wp_specialchars_decode( exactmetrics_get_upgrade_link( 'exactmetrics-notifications-sidebar', 'notifications', 'https://www.exactmetrics.com/lite/' ) );
|
130 |
-
}
|
131 |
-
|
132 |
-
/**
|
133 |
-
* Build external link by including UTM data
|
134 |
-
*
|
135 |
-
* @return string
|
136 |
-
*/
|
137 |
-
public function build_external_link( $url ) {
|
138 |
-
$build_url = wp_specialchars_decode( exactmetrics_get_url( 'exactmetrics-notifications-sidebar', 'notifications', $url ) );
|
139 |
-
$host = parse_url( $build_url, PHP_URL_HOST );
|
140 |
-
$domain_name = preg_replace( '/^www\./', '', $host );
|
141 |
-
|
142 |
-
if ( 'exactmetrics.com' != $domain_name ) {
|
143 |
-
parse_str( parse_url( $build_url, PHP_URL_QUERY ), $queries );
|
144 |
-
|
145 |
-
if ( isset( $queries['utm_source'] ) ) {
|
146 |
-
$queries['utm_source'] = 'exactmetrics';
|
147 |
-
}
|
148 |
-
|
149 |
-
$build_url = add_query_arg(
|
150 |
-
$queries,
|
151 |
-
trailingslashit( $url )
|
152 |
-
);
|
153 |
-
}
|
154 |
-
|
155 |
-
return $build_url;
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* Get the URL for the page where users can see/read notifications.
|
160 |
-
*
|
161 |
-
* @return string
|
162 |
-
*/
|
163 |
-
public function get_view_url( $scroll_to, $page, $tab='' ) {
|
164 |
-
return ExactMetrics()->notifications->get_view_url( $scroll_to, $page, $tab );
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* @param array $data
|
169 |
-
*
|
170 |
-
* @return array
|
171 |
-
*/
|
172 |
-
public function prepare_notification_data( $data ) {
|
173 |
-
return $data;
|
174 |
-
}
|
175 |
-
|
176 |
-
/**
|
177 |
-
* Add Notification not the notifications instance.
|
178 |
-
*
|
179 |
-
* @since 7.12.3
|
180 |
-
*/
|
181 |
-
public function add_notification() {
|
182 |
-
$notification = array();
|
183 |
-
$notification['id'] = $this->notification_id . '_' . date( 'Ymd' ); // Make sure we never add the same notification on the same day.
|
184 |
-
$notification['icon'] = $this->notification_icon;
|
185 |
-
$notification['title'] = '';
|
186 |
-
$notification['content'] = '';
|
187 |
-
$notification['type'] = $this->notification_type;
|
188 |
-
$notification['btns'] = array();
|
189 |
-
$notification['start'] = $this->notification_active_from;
|
190 |
-
$notification['end'] = $this->notification_active_for;
|
191 |
-
$notification_data = $this->prepare_notification_data( $notification );
|
192 |
-
|
193 |
-
if ( is_array( $notification_data ) && ! empty( $notification_data ) ) {
|
194 |
-
ExactMetrics()->notifications->add( $notification_data );
|
195 |
-
}
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* Get report
|
200 |
-
*
|
201 |
-
* @param string $report_name report name, default overview report.
|
202 |
-
* @param string $report_start_from report start date, default -30 days/last 30 days.
|
203 |
-
* @param string $report_end_to report end date, default -1 day/yesterday.
|
204 |
-
*
|
205 |
-
* @return array $data Overview data
|
206 |
-
*
|
207 |
-
* @since 7.12.3
|
208 |
-
*/
|
209 |
-
public function get_report( $report_name = 'overview', $report_start_from = '-30 day', $report_end_to = '-1 day' ) {
|
210 |
-
|
211 |
-
$report = ExactMetrics()->reporting->get_report( $report_name );
|
212 |
-
if ( $report ) {
|
213 |
-
// Mark the report request as coming from Notifications.
|
214 |
-
$report->set_report_source( 'notifications' );
|
215 |
-
}
|
216 |
-
$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
|
217 |
-
$args = array(
|
218 |
-
'start' => $this->get_formatted_date( $report_start_from ),
|
219 |
-
'end' => $this->get_formatted_date( $report_end_to ),
|
220 |
-
);
|
221 |
-
|
222 |
-
if ( $isnetwork ) {
|
223 |
-
$args['network'] = true;
|
224 |
-
}
|
225 |
-
|
226 |
-
if ( exactmetrics_is_pro_version() && ! ExactMetrics()->license->license_can( $report->level ) ) {
|
227 |
-
$data = array(
|
228 |
-
'success' => false,
|
229 |
-
'message' => __( "You don't have permission to view ExactMetrics reports.", 'google-analytics-dashboard-for-wp' ),
|
230 |
-
);
|
231 |
-
} else {
|
232 |
-
$data = $report->get_data( $args );
|
233 |
-
}
|
234 |
-
|
235 |
-
return $data;
|
236 |
-
}
|
237 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Parent Class for ExactMetrics Notification Event
|
4 |
+
*
|
5 |
+
* @since 7.12.3
|
6 |
+
*
|
7 |
+
* @package ExactMetrics
|
8 |
+
*/
|
9 |
+
|
10 |
+
class ExactMetrics_Notification_Event {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Generate unique notification id
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
*
|
17 |
+
* @since 7.12.3
|
18 |
+
*/
|
19 |
+
public $notification_id;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* When the notification will repeat (e.g: 7) here `7` to repeat the notification after each 7 days
|
23 |
+
* Only accept numeric value
|
24 |
+
*
|
25 |
+
* @var number
|
26 |
+
*
|
27 |
+
* @since 7.12.3
|
28 |
+
*/
|
29 |
+
public $notification_interval;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* When the notification will active, default: now
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
*
|
36 |
+
* @since 7.12.3
|
37 |
+
*/
|
38 |
+
public $notification_active_from;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* For how many days notification will be active
|
42 |
+
*
|
43 |
+
* @var string
|
44 |
+
*
|
45 |
+
* @since 7.12.3
|
46 |
+
*/
|
47 |
+
public $notification_active_for;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Which type of license is allowed to view this notification
|
51 |
+
*
|
52 |
+
* @var array
|
53 |
+
*
|
54 |
+
* @since 7.12.3
|
55 |
+
*/
|
56 |
+
public $notification_type;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Report start date if required e.g: "-15 day"(Readable Time)
|
60 |
+
*
|
61 |
+
* @var string
|
62 |
+
*
|
63 |
+
* @since 7.12.3
|
64 |
+
*/
|
65 |
+
public $report_start_from;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Report end date if required e.g: "-1 day"(Readable Time)
|
69 |
+
*
|
70 |
+
* @var string
|
71 |
+
*
|
72 |
+
* @since 7.12.3
|
73 |
+
*/
|
74 |
+
public $report_end_to;
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Notification icon to display with content
|
78 |
+
*
|
79 |
+
* @var string
|
80 |
+
*
|
81 |
+
* @since 7.12.3
|
82 |
+
*/
|
83 |
+
public $notification_icon;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Constructor
|
87 |
+
*
|
88 |
+
* @since 7.12.3
|
89 |
+
*/
|
90 |
+
public function __construct() {
|
91 |
+
|
92 |
+
$this->notification_active_from = date( 'm/d/Y g:i a', strtotime( 'now' ) );
|
93 |
+
$this->report_end_to = '-1 day'; // Yesterday.
|
94 |
+
|
95 |
+
if ( ! empty( $this->notification_id ) && ! empty( $this->notification_interval ) ) {
|
96 |
+
|
97 |
+
// Register notification in our custom runner.
|
98 |
+
exactmetrics_notification_event_runner()->register_notification( $this );
|
99 |
+
|
100 |
+
$this->notification_active_for = date( 'm/d/Y', strtotime( '+' . ( $this->notification_interval - 2 ) . ' day' ) );
|
101 |
+
$this->report_start_from = '-' . $this->notification_interval . ' day';
|
102 |
+
|
103 |
+
if ( ! isset( $this->notification_icon ) || empty( $this->notification_icon ) ) {
|
104 |
+
$this->notification_icon = 'default';
|
105 |
+
}
|
106 |
+
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get the formatted date.
|
112 |
+
*
|
113 |
+
* @param string $readable_time Readable time to convert to date.
|
114 |
+
*
|
115 |
+
* @return string date, format: Y-m-d
|
116 |
+
*
|
117 |
+
* @since 7.12.3
|
118 |
+
*/
|
119 |
+
public function get_formatted_date( $readable_time ) {
|
120 |
+
return date( 'Y-m-d', strtotime( $readable_time ) );
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Get the upgrade URL for pro plugin
|
125 |
+
*
|
126 |
+
* @return string
|
127 |
+
*/
|
128 |
+
public function get_upgrade_url() {
|
129 |
+
return wp_specialchars_decode( exactmetrics_get_upgrade_link( 'exactmetrics-notifications-sidebar', 'notifications', 'https://www.exactmetrics.com/lite/' ) );
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Build external link by including UTM data
|
134 |
+
*
|
135 |
+
* @return string
|
136 |
+
*/
|
137 |
+
public function build_external_link( $url ) {
|
138 |
+
$build_url = wp_specialchars_decode( exactmetrics_get_url( 'exactmetrics-notifications-sidebar', 'notifications', $url ) );
|
139 |
+
$host = parse_url( $build_url, PHP_URL_HOST );
|
140 |
+
$domain_name = preg_replace( '/^www\./', '', $host );
|
141 |
+
|
142 |
+
if ( 'exactmetrics.com' != $domain_name ) {
|
143 |
+
parse_str( parse_url( $build_url, PHP_URL_QUERY ), $queries );
|
144 |
+
|
145 |
+
if ( isset( $queries['utm_source'] ) ) {
|
146 |
+
$queries['utm_source'] = 'exactmetrics';
|
147 |
+
}
|
148 |
+
|
149 |
+
$build_url = add_query_arg(
|
150 |
+
$queries,
|
151 |
+
trailingslashit( $url )
|
152 |
+
);
|
153 |
+
}
|
154 |
+
|
155 |
+
return $build_url;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Get the URL for the page where users can see/read notifications.
|
160 |
+
*
|
161 |
+
* @return string
|
162 |
+
*/
|
163 |
+
public function get_view_url( $scroll_to, $page, $tab='' ) {
|
164 |
+
return ExactMetrics()->notifications->get_view_url( $scroll_to, $page, $tab );
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* @param array $data
|
169 |
+
*
|
170 |
+
* @return array
|
171 |
+
*/
|
172 |
+
public function prepare_notification_data( $data ) {
|
173 |
+
return $data;
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Add Notification not the notifications instance.
|
178 |
+
*
|
179 |
+
* @since 7.12.3
|
180 |
+
*/
|
181 |
+
public function add_notification() {
|
182 |
+
$notification = array();
|
183 |
+
$notification['id'] = $this->notification_id . '_' . date( 'Ymd' ); // Make sure we never add the same notification on the same day.
|
184 |
+
$notification['icon'] = $this->notification_icon;
|
185 |
+
$notification['title'] = '';
|
186 |
+
$notification['content'] = '';
|
187 |
+
$notification['type'] = $this->notification_type;
|
188 |
+
$notification['btns'] = array();
|
189 |
+
$notification['start'] = $this->notification_active_from;
|
190 |
+
$notification['end'] = $this->notification_active_for;
|
191 |
+
$notification_data = $this->prepare_notification_data( $notification );
|
192 |
+
|
193 |
+
if ( is_array( $notification_data ) && ! empty( $notification_data ) ) {
|
194 |
+
ExactMetrics()->notifications->add( $notification_data );
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Get report
|
200 |
+
*
|
201 |
+
* @param string $report_name report name, default overview report.
|
202 |
+
* @param string $report_start_from report start date, default -30 days/last 30 days.
|
203 |
+
* @param string $report_end_to report end date, default -1 day/yesterday.
|
204 |
+
*
|
205 |
+
* @return array $data Overview data
|
206 |
+
*
|
207 |
+
* @since 7.12.3
|
208 |
+
*/
|
209 |
+
public function get_report( $report_name = 'overview', $report_start_from = '-30 day', $report_end_to = '-1 day' ) {
|
210 |
+
|
211 |
+
$report = ExactMetrics()->reporting->get_report( $report_name );
|
212 |
+
if ( $report ) {
|
213 |
+
// Mark the report request as coming from Notifications.
|
214 |
+
$report->set_report_source( 'notifications' );
|
215 |
+
}
|
216 |
+
$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
|
217 |
+
$args = array(
|
218 |
+
'start' => $this->get_formatted_date( $report_start_from ),
|
219 |
+
'end' => $this->get_formatted_date( $report_end_to ),
|
220 |
+
);
|
221 |
+
|
222 |
+
if ( $isnetwork ) {
|
223 |
+
$args['network'] = true;
|
224 |
+
}
|
225 |
+
|
226 |
+
if ( exactmetrics_is_pro_version() && ! ExactMetrics()->license->license_can( $report->level ) ) {
|
227 |
+
$data = array(
|
228 |
+
'success' => false,
|
229 |
+
'message' => __( "You don't have permission to view ExactMetrics reports.", 'google-analytics-dashboard-for-wp' ),
|
230 |
+
);
|
231 |
+
} else {
|
232 |
+
$data = $report->get_data( $args );
|
233 |
+
}
|
234 |
+
|
235 |
+
return $data;
|
236 |
+
}
|
237 |
+
}
|
includes/admin/notifications/notification-audience.php
CHANGED
@@ -1,101 +1,101 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add audience notification
|
5 |
-
* Recurrence: 30 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Audience extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_audience';
|
12 |
-
public $notification_interval = 30; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Build Notification
|
17 |
-
*
|
18 |
-
* @param array $notification
|
19 |
-
* @param array $data
|
20 |
-
*
|
21 |
-
* @return array $notification notification is ready to add
|
22 |
-
*
|
23 |
-
* @since 7.12.3
|
24 |
-
*/
|
25 |
-
public function prepare_notification_data( $notification ) {
|
26 |
-
$data = $this->get_notification_data();
|
27 |
-
|
28 |
-
if ( ! is_array( $data ) || empty( $data ) ) {
|
29 |
-
return false;
|
30 |
-
}
|
31 |
-
|
32 |
-
// Translators: Audience notification title
|
33 |
-
$notification['title'] = sprintf( __( '%s%% of your Audience is from %s', 'google-analytics-dashboard-for-wp' ), $data['percentage'], $data['country'] );
|
34 |
-
// Translators: Audience notification content
|
35 |
-
$notification['content'] = sprintf( __( 'Is your site properly translated? By adding translated content specific to your audience you could gain big boosts in pageviews, time spent on page and a reduced bounce rate.<br><br>If you need help choosing a translation plugin to get you started take a look at %sthis article%s for the best options available.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.wpbeginner.com/showcase/9-best-translation-plugins-for-wordpress-websites/' ) . '" target="_blank">', '</a>' );
|
36 |
-
$notification['btns'] = array(
|
37 |
-
"view_report" => array(
|
38 |
-
'url' => $this->get_view_url( 'exactmetrics-report-top-countries', 'exactmetrics_reports' ),
|
39 |
-
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
40 |
-
),
|
41 |
-
"learn_more" => array(
|
42 |
-
'url' => $this->build_external_link( 'https://www.wpbeginner.com/showcase/9-best-translation-plugins-for-wordpress-websites/' ),
|
43 |
-
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
44 |
-
'is_external' => true,
|
45 |
-
),
|
46 |
-
);
|
47 |
-
|
48 |
-
return $notification;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Add report to notifications
|
53 |
-
*
|
54 |
-
* @since 7.12.3
|
55 |
-
*/
|
56 |
-
public function get_notification_data() {
|
57 |
-
require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
|
58 |
-
|
59 |
-
$data = array();
|
60 |
-
$report = $this->get_report();
|
61 |
-
$sessions = isset( $report['data']['infobox']['sessions']['value'] ) ? $report['data']['infobox']['sessions']['value'] : 0;
|
62 |
-
$countries = isset( $report['data']['countries'] ) ? $report['data']['countries'] : 0;
|
63 |
-
$english_speaking_countries = exactmetrics_get_english_speaking_countries();
|
64 |
-
|
65 |
-
if ( $sessions > 0 && is_array( $countries ) && ! empty( $countries ) ) {
|
66 |
-
foreach ( $countries as $country ) {
|
67 |
-
if ( empty( $country['iso'] ) || array_key_exists( $country['iso'], $english_speaking_countries ) ) {
|
68 |
-
continue;
|
69 |
-
}
|
70 |
-
|
71 |
-
if ( $country['sessions'] > 0 ) {
|
72 |
-
// get the country's session percentage by comparing with the total sessions
|
73 |
-
$country_session_percentage = round( $country['sessions'] * 100 / $sessions );
|
74 |
-
|
75 |
-
if ( $country_session_percentage < 15 ) {
|
76 |
-
continue;
|
77 |
-
}
|
78 |
-
|
79 |
-
$site_language = get_locale();
|
80 |
-
$translations = wp_get_available_translations();
|
81 |
-
|
82 |
-
if ( is_array( $translations ) && ! empty( $translations ) ) {
|
83 |
-
$site_iso = isset( $translations[ $site_language ]['iso'] ) ? $translations[ $site_language ]['iso'] : array(); // keep empty array, because site language has no iso setup for en_US language
|
84 |
-
|
85 |
-
if ( is_array( $site_iso ) && ! in_array( $country['iso'], $site_iso ) ) {
|
86 |
-
$data['country'] = $country['name'];
|
87 |
-
$data['percentage'] = $country_session_percentage;
|
88 |
-
break;
|
89 |
-
}
|
90 |
-
}
|
91 |
-
}
|
92 |
-
}
|
93 |
-
}
|
94 |
-
|
95 |
-
return $data;
|
96 |
-
}
|
97 |
-
|
98 |
-
}
|
99 |
-
|
100 |
-
// initiate the class
|
101 |
-
new ExactMetrics_Notification_Audience();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add audience notification
|
5 |
+
* Recurrence: 30 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Audience extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_audience';
|
12 |
+
public $notification_interval = 30; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Build Notification
|
17 |
+
*
|
18 |
+
* @param array $notification
|
19 |
+
* @param array $data
|
20 |
+
*
|
21 |
+
* @return array $notification notification is ready to add
|
22 |
+
*
|
23 |
+
* @since 7.12.3
|
24 |
+
*/
|
25 |
+
public function prepare_notification_data( $notification ) {
|
26 |
+
$data = $this->get_notification_data();
|
27 |
+
|
28 |
+
if ( ! is_array( $data ) || empty( $data ) ) {
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
|
32 |
+
// Translators: Audience notification title
|
33 |
+
$notification['title'] = sprintf( __( '%s%% of your Audience is from %s', 'google-analytics-dashboard-for-wp' ), $data['percentage'], $data['country'] );
|
34 |
+
// Translators: Audience notification content
|
35 |
+
$notification['content'] = sprintf( __( 'Is your site properly translated? By adding translated content specific to your audience you could gain big boosts in pageviews, time spent on page and a reduced bounce rate.<br><br>If you need help choosing a translation plugin to get you started take a look at %sthis article%s for the best options available.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.wpbeginner.com/showcase/9-best-translation-plugins-for-wordpress-websites/' ) . '" target="_blank">', '</a>' );
|
36 |
+
$notification['btns'] = array(
|
37 |
+
"view_report" => array(
|
38 |
+
'url' => $this->get_view_url( 'exactmetrics-report-top-countries', 'exactmetrics_reports' ),
|
39 |
+
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
40 |
+
),
|
41 |
+
"learn_more" => array(
|
42 |
+
'url' => $this->build_external_link( 'https://www.wpbeginner.com/showcase/9-best-translation-plugins-for-wordpress-websites/' ),
|
43 |
+
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
44 |
+
'is_external' => true,
|
45 |
+
),
|
46 |
+
);
|
47 |
+
|
48 |
+
return $notification;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Add report to notifications
|
53 |
+
*
|
54 |
+
* @since 7.12.3
|
55 |
+
*/
|
56 |
+
public function get_notification_data() {
|
57 |
+
require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
|
58 |
+
|
59 |
+
$data = array();
|
60 |
+
$report = $this->get_report();
|
61 |
+
$sessions = isset( $report['data']['infobox']['sessions']['value'] ) ? $report['data']['infobox']['sessions']['value'] : 0;
|
62 |
+
$countries = isset( $report['data']['countries'] ) ? $report['data']['countries'] : 0;
|
63 |
+
$english_speaking_countries = exactmetrics_get_english_speaking_countries();
|
64 |
+
|
65 |
+
if ( $sessions > 0 && is_array( $countries ) && ! empty( $countries ) ) {
|
66 |
+
foreach ( $countries as $country ) {
|
67 |
+
if ( empty( $country['iso'] ) || array_key_exists( $country['iso'], $english_speaking_countries ) ) {
|
68 |
+
continue;
|
69 |
+
}
|
70 |
+
|
71 |
+
if ( $country['sessions'] > 0 ) {
|
72 |
+
// get the country's session percentage by comparing with the total sessions
|
73 |
+
$country_session_percentage = round( $country['sessions'] * 100 / $sessions );
|
74 |
+
|
75 |
+
if ( $country_session_percentage < 15 ) {
|
76 |
+
continue;
|
77 |
+
}
|
78 |
+
|
79 |
+
$site_language = get_locale();
|
80 |
+
$translations = wp_get_available_translations();
|
81 |
+
|
82 |
+
if ( is_array( $translations ) && ! empty( $translations ) ) {
|
83 |
+
$site_iso = isset( $translations[ $site_language ]['iso'] ) ? $translations[ $site_language ]['iso'] : array(); // keep empty array, because site language has no iso setup for en_US language
|
84 |
+
|
85 |
+
if ( is_array( $site_iso ) && ! in_array( $country['iso'], $site_iso ) ) {
|
86 |
+
$data['country'] = $country['name'];
|
87 |
+
$data['percentage'] = $country_session_percentage;
|
88 |
+
break;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
return $data;
|
96 |
+
}
|
97 |
+
|
98 |
+
}
|
99 |
+
|
100 |
+
// initiate the class
|
101 |
+
new ExactMetrics_Notification_Audience();
|
includes/admin/notifications/notification-bounce-rate.php
CHANGED
@@ -1,54 +1,54 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when bounce rate is higher than 70%
|
5 |
-
* Recurrence: Once weekly
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Bounce_Rate extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_bounce_rate';
|
12 |
-
public $notification_interval = 7; // In days.
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Build Notification data.
|
17 |
-
*
|
18 |
-
* @param array $notification The notification data array to filter.
|
19 |
-
*
|
20 |
-
* @return array|bool $notification notification is ready to add or false if no data.
|
21 |
-
*
|
22 |
-
* @since 7.12.3
|
23 |
-
*/
|
24 |
-
public function prepare_notification_data( $notification ) {
|
25 |
-
$data = array();
|
26 |
-
$report = $this->get_report( 'overview' );
|
27 |
-
$data['bounce_rate'] = isset( $report['data']['infobox']['bounce']['value'] ) ? $report['data']['infobox']['bounce']['value'] : 0;
|
28 |
-
|
29 |
-
if ( ! empty( $data ) && $data['bounce_rate'] > 70 ) {
|
30 |
-
$notification['title'] = __( 'Your website bounce rate is higher than 70%', 'google-analytics-dashboard-for-wp' );
|
31 |
-
// Translators: Bounce rate notification content.
|
32 |
-
$notification['content'] = sprintf( __( 'Your website bounce rate is %1$s. High bounce rates can hurt your site’s conversions rates. A high bounce rate might mean that people aren\'t finding what they\'re looking for on your site. %2$sHere%3$s are some points to remember and steps to follow to get your bounce rates back to manageable levels.', 'google-analytics-dashboard-for-wp' ), $data['bounce_rate'], '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/how-to-reduce-bounce-rate/' ) . '" target="_blank">', '</a>' );
|
33 |
-
$notification['btns'] = array(
|
34 |
-
'view_report' => array(
|
35 |
-
'url' => $this->get_view_url( 'exactmetrics-report-infobox-bounce-rate', 'exactmetrics_reports' ),
|
36 |
-
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' ),
|
37 |
-
),
|
38 |
-
'learn_more' => array(
|
39 |
-
'url' => $this->build_external_link( 'https://www.exactmetrics.com/how-to-reduce-bounce-rate/' ),
|
40 |
-
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
41 |
-
'is_external' => true,
|
42 |
-
),
|
43 |
-
);
|
44 |
-
|
45 |
-
return $notification;
|
46 |
-
}
|
47 |
-
|
48 |
-
return false;
|
49 |
-
}
|
50 |
-
|
51 |
-
}
|
52 |
-
|
53 |
-
// initialize the class
|
54 |
-
new ExactMetrics_Notification_Bounce_Rate();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when bounce rate is higher than 70%
|
5 |
+
* Recurrence: Once weekly
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Bounce_Rate extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_bounce_rate';
|
12 |
+
public $notification_interval = 7; // In days.
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Build Notification data.
|
17 |
+
*
|
18 |
+
* @param array $notification The notification data array to filter.
|
19 |
+
*
|
20 |
+
* @return array|bool $notification notification is ready to add or false if no data.
|
21 |
+
*
|
22 |
+
* @since 7.12.3
|
23 |
+
*/
|
24 |
+
public function prepare_notification_data( $notification ) {
|
25 |
+
$data = array();
|
26 |
+
$report = $this->get_report( 'overview' );
|
27 |
+
$data['bounce_rate'] = isset( $report['data']['infobox']['bounce']['value'] ) ? $report['data']['infobox']['bounce']['value'] : 0;
|
28 |
+
|
29 |
+
if ( ! empty( $data ) && $data['bounce_rate'] > 70 ) {
|
30 |
+
$notification['title'] = __( 'Your website bounce rate is higher than 70%', 'google-analytics-dashboard-for-wp' );
|
31 |
+
// Translators: Bounce rate notification content.
|
32 |
+
$notification['content'] = sprintf( __( 'Your website bounce rate is %1$s. High bounce rates can hurt your site’s conversions rates. A high bounce rate might mean that people aren\'t finding what they\'re looking for on your site. %2$sHere%3$s are some points to remember and steps to follow to get your bounce rates back to manageable levels.', 'google-analytics-dashboard-for-wp' ), $data['bounce_rate'], '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/how-to-reduce-bounce-rate/' ) . '" target="_blank">', '</a>' );
|
33 |
+
$notification['btns'] = array(
|
34 |
+
'view_report' => array(
|
35 |
+
'url' => $this->get_view_url( 'exactmetrics-report-infobox-bounce-rate', 'exactmetrics_reports' ),
|
36 |
+
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' ),
|
37 |
+
),
|
38 |
+
'learn_more' => array(
|
39 |
+
'url' => $this->build_external_link( 'https://www.exactmetrics.com/how-to-reduce-bounce-rate/' ),
|
40 |
+
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
41 |
+
'is_external' => true,
|
42 |
+
),
|
43 |
+
);
|
44 |
+
|
45 |
+
return $notification;
|
46 |
+
}
|
47 |
+
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
|
51 |
+
}
|
52 |
+
|
53 |
+
// initialize the class
|
54 |
+
new ExactMetrics_Notification_Bounce_Rate();
|
includes/admin/notifications/notification-events.php
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
$base = ExactMetrics();
|
4 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-visitors.php';
|
5 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-audience.php';
|
6 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-mobile-device.php';
|
7 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-to-pro.php';
|
8 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-bounce-rate.php';
|
9 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-returning-visitors.php';
|
10 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-traffic-dropping.php';
|
11 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-search-console.php';
|
12 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-form-conversion.php';
|
13 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-email-summaries.php';
|
14 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-google-optimize.php';
|
15 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-to-add-more-file-extensions.php';
|
16 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-to-setup-affiliate-links.php';
|
17 |
-
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-headline-analyzer.php';
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$base = ExactMetrics();
|
4 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-visitors.php';
|
5 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-audience.php';
|
6 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-mobile-device.php';
|
7 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-to-pro.php';
|
8 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-bounce-rate.php';
|
9 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-returning-visitors.php';
|
10 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-traffic-dropping.php';
|
11 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-search-console.php';
|
12 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-form-conversion.php';
|
13 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-email-summaries.php';
|
14 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-upgrade-for-google-optimize.php';
|
15 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-to-add-more-file-extensions.php';
|
16 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-to-setup-affiliate-links.php';
|
17 |
+
require_once plugin_dir_path( $base->file ) . '/includes/admin/notifications/notification-headline-analyzer.php';
|
includes/admin/notifications/notification-headline-analyzer.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification for headline analyzer
|
5 |
-
* Recurrence: 60 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Headline_Analyzer extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_headline_analyzer';
|
12 |
-
public $notification_interval = 60; // in days
|
13 |
-
public $notification_first_run_time = '+7 day';
|
14 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Build Notification
|
18 |
-
*
|
19 |
-
* @return array $notification notification is ready to add
|
20 |
-
*
|
21 |
-
* @since 7.12.3
|
22 |
-
*/
|
23 |
-
public function prepare_notification_data( $notification ) {
|
24 |
-
$notification['title'] = __( 'Headline Analyzer to Boost Your Clicks & Traffic', 'google-analytics-dashboard-for-wp' );
|
25 |
-
// Translators: Headline Analyzer notification content.
|
26 |
-
$notification['content'] = sprintf( __( 'Did you know that 36%% of SEO experts think the headline is the most important SEO element? Yet many website owners don’t know how to optimize their headlines for SEO and clicks. Instead, they write copy and hope for the best, only to see disappointing results. Now there’s an easier way! <br><br>%1$sWith the ExactMetrics Headline Analyzer%2$s, you can get targeted suggestions to improve your headlines, right in the WordPress editor.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/introducing-exactmetrics-built-in-headline-analyzer/' ) . '" target="_blank">', '</a>' );
|
27 |
-
$notification['btns'] = array(
|
28 |
-
"learn_more" => array(
|
29 |
-
'url' => $this->build_external_link( 'https://www.exactmetrics.com/introducing-exactmetrics-built-in-headline-analyzer/' ),
|
30 |
-
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
31 |
-
'is_external' => true,
|
32 |
-
),
|
33 |
-
);
|
34 |
-
|
35 |
-
return $notification;
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
// initialize the class
|
41 |
-
new ExactMetrics_Notification_Headline_Analyzer();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification for headline analyzer
|
5 |
+
* Recurrence: 60 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Headline_Analyzer extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_headline_analyzer';
|
12 |
+
public $notification_interval = 60; // in days
|
13 |
+
public $notification_first_run_time = '+7 day';
|
14 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Build Notification
|
18 |
+
*
|
19 |
+
* @return array $notification notification is ready to add
|
20 |
+
*
|
21 |
+
* @since 7.12.3
|
22 |
+
*/
|
23 |
+
public function prepare_notification_data( $notification ) {
|
24 |
+
$notification['title'] = __( 'Headline Analyzer to Boost Your Clicks & Traffic', 'google-analytics-dashboard-for-wp' );
|
25 |
+
// Translators: Headline Analyzer notification content.
|
26 |
+
$notification['content'] = sprintf( __( 'Did you know that 36%% of SEO experts think the headline is the most important SEO element? Yet many website owners don’t know how to optimize their headlines for SEO and clicks. Instead, they write copy and hope for the best, only to see disappointing results. Now there’s an easier way! <br><br>%1$sWith the ExactMetrics Headline Analyzer%2$s, you can get targeted suggestions to improve your headlines, right in the WordPress editor.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/introducing-exactmetrics-built-in-headline-analyzer/' ) . '" target="_blank">', '</a>' );
|
27 |
+
$notification['btns'] = array(
|
28 |
+
"learn_more" => array(
|
29 |
+
'url' => $this->build_external_link( 'https://www.exactmetrics.com/introducing-exactmetrics-built-in-headline-analyzer/' ),
|
30 |
+
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
31 |
+
'is_external' => true,
|
32 |
+
),
|
33 |
+
);
|
34 |
+
|
35 |
+
return $notification;
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
+
// initialize the class
|
41 |
+
new ExactMetrics_Notification_Headline_Analyzer();
|
includes/admin/notifications/notification-mobile-device.php
CHANGED
@@ -1,53 +1,53 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when percentage of visitors from mobile device is less than 10%
|
5 |
-
* Recurrence: 15 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Mobile_Device extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_mobile_device';
|
12 |
-
public $notification_interval = 15; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Prepare Notification
|
17 |
-
*
|
18 |
-
* @return array $notification notification is ready to add
|
19 |
-
*
|
20 |
-
* @since 7.12.3
|
21 |
-
*/
|
22 |
-
public function prepare_notification_data( $notification ) {
|
23 |
-
$data = array();
|
24 |
-
$report = $this->get_report( 'overview', $this->report_start_from, $this->report_end_to );
|
25 |
-
$data['percentage_of_mobile_visitors'] = isset( $report['data']['devices']['mobile'] ) ? $report['data']['devices']['mobile'] : 0;
|
26 |
-
|
27 |
-
if ( ! empty( $data ) && $data['percentage_of_mobile_visitors'] < 10 ) {
|
28 |
-
// Translators: Mobile device notification title
|
29 |
-
$notification['title'] = sprintf( __( 'Traffic from Mobile Devices is %s%%', 'google-analytics-dashboard-for-wp' ), $data['percentage_of_mobile_visitors'] );
|
30 |
-
// Translators: Mobile device notification content
|
31 |
-
$notification['content'] = sprintf( __( 'Traffic from mobile devices is considerably lower on your site compared to desktop devices. This could be an indicator that your site is not optimised for mobile devices.<br><br>Take a look now at %show your site looks%s on mobile and make sure all your content can be accessed correctly.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.wpbeginner.com/beginners-guide/how-to-preview-the-mobile-layout-of-your-site/' ) . '" target="_blank">', '</a>' );
|
32 |
-
$notification['btns'] = array(
|
33 |
-
"view_report" => array(
|
34 |
-
'url' => $this->get_view_url( 'devices', 'exactmetrics_reports' ),
|
35 |
-
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
36 |
-
),
|
37 |
-
"learn_more" => array(
|
38 |
-
'url' => $this->build_external_link( 'https://www.wpbeginner.com/beginners-guide/how-to-preview-the-mobile-layout-of-your-site/' ),
|
39 |
-
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
40 |
-
'is_external' => true,
|
41 |
-
),
|
42 |
-
);
|
43 |
-
|
44 |
-
return $notification;
|
45 |
-
}
|
46 |
-
|
47 |
-
return false;
|
48 |
-
}
|
49 |
-
|
50 |
-
}
|
51 |
-
|
52 |
-
// initialize the class
|
53 |
-
new ExactMetrics_Notification_Mobile_Device();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when percentage of visitors from mobile device is less than 10%
|
5 |
+
* Recurrence: 15 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Mobile_Device extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_mobile_device';
|
12 |
+
public $notification_interval = 15; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Prepare Notification
|
17 |
+
*
|
18 |
+
* @return array $notification notification is ready to add
|
19 |
+
*
|
20 |
+
* @since 7.12.3
|
21 |
+
*/
|
22 |
+
public function prepare_notification_data( $notification ) {
|
23 |
+
$data = array();
|
24 |
+
$report = $this->get_report( 'overview', $this->report_start_from, $this->report_end_to );
|
25 |
+
$data['percentage_of_mobile_visitors'] = isset( $report['data']['devices']['mobile'] ) ? $report['data']['devices']['mobile'] : 0;
|
26 |
+
|
27 |
+
if ( ! empty( $data ) && $data['percentage_of_mobile_visitors'] < 10 ) {
|
28 |
+
// Translators: Mobile device notification title
|
29 |
+
$notification['title'] = sprintf( __( 'Traffic from Mobile Devices is %s%%', 'google-analytics-dashboard-for-wp' ), $data['percentage_of_mobile_visitors'] );
|
30 |
+
// Translators: Mobile device notification content
|
31 |
+
$notification['content'] = sprintf( __( 'Traffic from mobile devices is considerably lower on your site compared to desktop devices. This could be an indicator that your site is not optimised for mobile devices.<br><br>Take a look now at %show your site looks%s on mobile and make sure all your content can be accessed correctly.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.wpbeginner.com/beginners-guide/how-to-preview-the-mobile-layout-of-your-site/' ) . '" target="_blank">', '</a>' );
|
32 |
+
$notification['btns'] = array(
|
33 |
+
"view_report" => array(
|
34 |
+
'url' => $this->get_view_url( 'devices', 'exactmetrics_reports' ),
|
35 |
+
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
36 |
+
),
|
37 |
+
"learn_more" => array(
|
38 |
+
'url' => $this->build_external_link( 'https://www.wpbeginner.com/beginners-guide/how-to-preview-the-mobile-layout-of-your-site/' ),
|
39 |
+
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
40 |
+
'is_external' => true,
|
41 |
+
),
|
42 |
+
);
|
43 |
+
|
44 |
+
return $notification;
|
45 |
+
}
|
46 |
+
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
// initialize the class
|
53 |
+
new ExactMetrics_Notification_Mobile_Device();
|
includes/admin/notifications/notification-returning-visitors.php
CHANGED
@@ -1,53 +1,53 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when returning visitor rate is lower than 10%
|
5 |
-
* Recurrence: 15 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Returning_Visitors extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_returning_visitors';
|
12 |
-
public $notification_interval = 15; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Build Notification
|
17 |
-
*
|
18 |
-
* @return array $notification notification is ready to add
|
19 |
-
*
|
20 |
-
* @since 7.12.3
|
21 |
-
*/
|
22 |
-
public function prepare_notification_data( $notification ) {
|
23 |
-
$data = array();
|
24 |
-
$report = $this->get_report( 'overview', $this->report_start_from, $this->report_end_to );
|
25 |
-
$data['returning'] = isset( $report['data']['newvsreturn']['returning'] ) ? $report['data']['newvsreturn']['returning'] : 0;
|
26 |
-
|
27 |
-
if ( ! empty( $data ) && $data['returning'] < 10 ) {
|
28 |
-
// Translators: Returning visitors notification title
|
29 |
-
$notification['title'] = sprintf( __( 'Only %s%% of your visitors return to your site', 'google-analytics-dashboard-for-wp' ), $data['returning'] );
|
30 |
-
// Translators: Returning visitors notification content
|
31 |
-
$notification['content'] = sprintf( __( 'For any website, returning visitors are important because they indicate how successful your marketing campaigns are, who are your loyal customers, and how powerful your brand is. %sIn this article%s, we’ll show you 7 proven ways to increase your returning visitor rate.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/proven-ways-to-increase-your-returning-visitor-rate/' ) . '" target="_blank">', '</a>' );
|
32 |
-
$notification['btns'] = array(
|
33 |
-
"view_report" => array(
|
34 |
-
'url' => $this->get_view_url( 'newvsreturning', 'exactmetrics_reports' ),
|
35 |
-
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
36 |
-
),
|
37 |
-
"learn_more" => array(
|
38 |
-
'url' => $this->build_external_link( 'https://www.exactmetrics.com/proven-ways-to-increase-your-returning-visitor-rate/' ),
|
39 |
-
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
40 |
-
'is_external' => true,
|
41 |
-
),
|
42 |
-
);
|
43 |
-
|
44 |
-
return $notification;
|
45 |
-
}
|
46 |
-
|
47 |
-
return false;
|
48 |
-
}
|
49 |
-
|
50 |
-
}
|
51 |
-
|
52 |
-
// initialize the class
|
53 |
-
new ExactMetrics_Notification_Returning_Visitors();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when returning visitor rate is lower than 10%
|
5 |
+
* Recurrence: 15 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Returning_Visitors extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_returning_visitors';
|
12 |
+
public $notification_interval = 15; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Build Notification
|
17 |
+
*
|
18 |
+
* @return array $notification notification is ready to add
|
19 |
+
*
|
20 |
+
* @since 7.12.3
|
21 |
+
*/
|
22 |
+
public function prepare_notification_data( $notification ) {
|
23 |
+
$data = array();
|
24 |
+
$report = $this->get_report( 'overview', $this->report_start_from, $this->report_end_to );
|
25 |
+
$data['returning'] = isset( $report['data']['newvsreturn']['returning'] ) ? $report['data']['newvsreturn']['returning'] : 0;
|
26 |
+
|
27 |
+
if ( ! empty( $data ) && $data['returning'] < 10 ) {
|
28 |
+
// Translators: Returning visitors notification title
|
29 |
+
$notification['title'] = sprintf( __( 'Only %s%% of your visitors return to your site', 'google-analytics-dashboard-for-wp' ), $data['returning'] );
|
30 |
+
// Translators: Returning visitors notification content
|
31 |
+
$notification['content'] = sprintf( __( 'For any website, returning visitors are important because they indicate how successful your marketing campaigns are, who are your loyal customers, and how powerful your brand is. %sIn this article%s, we’ll show you 7 proven ways to increase your returning visitor rate.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/proven-ways-to-increase-your-returning-visitor-rate/' ) . '" target="_blank">', '</a>' );
|
32 |
+
$notification['btns'] = array(
|
33 |
+
"view_report" => array(
|
34 |
+
'url' => $this->get_view_url( 'newvsreturning', 'exactmetrics_reports' ),
|
35 |
+
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
36 |
+
),
|
37 |
+
"learn_more" => array(
|
38 |
+
'url' => $this->build_external_link( 'https://www.exactmetrics.com/proven-ways-to-increase-your-returning-visitor-rate/' ),
|
39 |
+
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
40 |
+
'is_external' => true,
|
41 |
+
),
|
42 |
+
);
|
43 |
+
|
44 |
+
return $notification;
|
45 |
+
}
|
46 |
+
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
// initialize the class
|
53 |
+
new ExactMetrics_Notification_Returning_Visitors();
|
includes/admin/notifications/notification-to-add-more-file-extensions.php
CHANGED
@@ -1,48 +1,48 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when there is no extension added or only the default extensions exist
|
5 |
-
* Recurrence: 20 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_To_Add_More_File_Extensions extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_to_add_more_file_extensions';
|
12 |
-
public $notification_interval = 20; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Build Notification
|
17 |
-
*
|
18 |
-
* @return array $notification notification is ready to add
|
19 |
-
*
|
20 |
-
* @since 7.12.3
|
21 |
-
*/
|
22 |
-
public function prepare_notification_data( $notification ) {
|
23 |
-
$download_extensions = exactmetrics_get_option( 'extensions_of_files', '' );
|
24 |
-
|
25 |
-
if ( empty( $download_extensions ) || "doc,pdf,ppt,zip,xls,docx,pptx,xlsx" === $download_extensions ) {
|
26 |
-
|
27 |
-
$settings_url = is_network_admin() ? $this->get_view_url( 'exactmetrics-settings-block-file-downloads', 'exactmetrics_network', 'engagement' ) : $this->get_view_url( 'exactmetrics-settings-block-file-downloads', 'exactmetrics_settings', 'engagement' );
|
28 |
-
$publishers_report_url = $this->get_view_url( 'exactmetrics-report-download-links', 'exactmetrics_reports', 'publishers' );
|
29 |
-
$notification['title'] = __( 'Add More File Extensions to Track as Downloads', 'google-analytics-dashboard-for-wp' );
|
30 |
-
// Translators: File extensions notification content
|
31 |
-
$notification['content'] = sprintf( __( 'By default, ExactMetrics automatically tracks downloads of the following file extensions: doc, pdf, ppt, zip, xls, docx, pptx, and xlsx. You can easily add or remove extensions from that list in the %sEngagement settings%s of ExactMetrics.<br><br> You can view your Top Downloads report directly in the ExactMetrics %sPublishers report%s.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $settings_url . '">', '</a>', '<a href="' . $publishers_report_url . '">', '</a>' );
|
32 |
-
$notification['btns'] = array(
|
33 |
-
"add_more_file_extensions" => array(
|
34 |
-
'url' => $settings_url,
|
35 |
-
'text' => __( 'Add File Extensions', 'google-analytics-dashboard-for-wp' )
|
36 |
-
),
|
37 |
-
);
|
38 |
-
|
39 |
-
return $notification;
|
40 |
-
}
|
41 |
-
|
42 |
-
return false;
|
43 |
-
}
|
44 |
-
|
45 |
-
}
|
46 |
-
|
47 |
-
// initialize the class
|
48 |
-
new ExactMetrics_Notification_To_Add_More_File_Extensions();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when there is no extension added or only the default extensions exist
|
5 |
+
* Recurrence: 20 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_To_Add_More_File_Extensions extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_to_add_more_file_extensions';
|
12 |
+
public $notification_interval = 20; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Build Notification
|
17 |
+
*
|
18 |
+
* @return array $notification notification is ready to add
|
19 |
+
*
|
20 |
+
* @since 7.12.3
|
21 |
+
*/
|
22 |
+
public function prepare_notification_data( $notification ) {
|
23 |
+
$download_extensions = exactmetrics_get_option( 'extensions_of_files', '' );
|
24 |
+
|
25 |
+
if ( empty( $download_extensions ) || "doc,pdf,ppt,zip,xls,docx,pptx,xlsx" === $download_extensions ) {
|
26 |
+
|
27 |
+
$settings_url = is_network_admin() ? $this->get_view_url( 'exactmetrics-settings-block-file-downloads', 'exactmetrics_network', 'engagement' ) : $this->get_view_url( 'exactmetrics-settings-block-file-downloads', 'exactmetrics_settings', 'engagement' );
|
28 |
+
$publishers_report_url = $this->get_view_url( 'exactmetrics-report-download-links', 'exactmetrics_reports', 'publishers' );
|
29 |
+
$notification['title'] = __( 'Add More File Extensions to Track as Downloads', 'google-analytics-dashboard-for-wp' );
|
30 |
+
// Translators: File extensions notification content
|
31 |
+
$notification['content'] = sprintf( __( 'By default, ExactMetrics automatically tracks downloads of the following file extensions: doc, pdf, ppt, zip, xls, docx, pptx, and xlsx. You can easily add or remove extensions from that list in the %sEngagement settings%s of ExactMetrics.<br><br> You can view your Top Downloads report directly in the ExactMetrics %sPublishers report%s.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $settings_url . '">', '</a>', '<a href="' . $publishers_report_url . '">', '</a>' );
|
32 |
+
$notification['btns'] = array(
|
33 |
+
"add_more_file_extensions" => array(
|
34 |
+
'url' => $settings_url,
|
35 |
+
'text' => __( 'Add File Extensions', 'google-analytics-dashboard-for-wp' )
|
36 |
+
),
|
37 |
+
);
|
38 |
+
|
39 |
+
return $notification;
|
40 |
+
}
|
41 |
+
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
|
45 |
+
}
|
46 |
+
|
47 |
+
// initialize the class
|
48 |
+
new ExactMetrics_Notification_To_Add_More_File_Extensions();
|
includes/admin/notifications/notification-to-setup-affiliate-links.php
CHANGED
@@ -1,54 +1,54 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when no links set up for Affiliate tracking or just the default links exist
|
5 |
-
* Recurrence: 25 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_To_Setup_Affiliate_Links extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_to_setup_affiliate_links';
|
12 |
-
public $notification_interval = 25; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Build Notification
|
17 |
-
*
|
18 |
-
* @return array $notification notification is ready to add
|
19 |
-
*
|
20 |
-
* @since 7.12.3
|
21 |
-
*/
|
22 |
-
public function prepare_notification_data( $notification ) {
|
23 |
-
$affiliate_links = exactmetrics_get_option( 'affiliate_links', array() );
|
24 |
-
$no_new_links = false;
|
25 |
-
|
26 |
-
if ( is_array( $affiliate_links ) && ! empty( $affiliate_links ) ) {
|
27 |
-
if ( 2 === count( $affiliate_links ) && isset( $affiliate_links[0]['path'] ) && isset( $affiliate_links[1]['path'] ) ) {
|
28 |
-
$no_new_links = "/go/" === $affiliate_links[0]['path'] && "/recommend/" === $affiliate_links[1]['path'] ? true : false;
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
32 |
-
if ( true === $no_new_links || ( is_array( $affiliate_links ) && empty( $affiliate_links ) ) ) {
|
33 |
-
|
34 |
-
$notification['title'] = __( 'Set Up Affiliate Link Tracking', 'google-analytics-dashboard-for-wp' );
|
35 |
-
// Translators: Set up affiliate links notification content
|
36 |
-
$notification['content'] = sprintf( __( 'By tracking your affiliate links in Google Analytics, you can gather all the data you need to optimize your links for maximizing affiliate revenue. You can track affiliate link clicks on your website with little configuration needed.<br><br>%sIn this article%s, we’ll show you how to set up affiliate link tracking in WordPress.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/how-to-set-up-affiliate-link-tracking-in-wordpress/' ) . '" target="_blank">', '</a>' );
|
37 |
-
$notification['btns'] = array(
|
38 |
-
"read_more" => array(
|
39 |
-
'url' => $this->build_external_link( 'https://www.exactmetrics.com/how-to-set-up-affiliate-link-tracking-in-wordpress/' ),
|
40 |
-
'text' => __( 'Read More', 'google-analytics-dashboard-for-wp' ),
|
41 |
-
'is_external' => true,
|
42 |
-
),
|
43 |
-
);
|
44 |
-
|
45 |
-
return $notification;
|
46 |
-
}
|
47 |
-
|
48 |
-
return false;
|
49 |
-
}
|
50 |
-
|
51 |
-
}
|
52 |
-
|
53 |
-
// initialize the class
|
54 |
-
new ExactMetrics_Notification_To_Setup_Affiliate_Links();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when no links set up for Affiliate tracking or just the default links exist
|
5 |
+
* Recurrence: 25 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_To_Setup_Affiliate_Links extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_to_setup_affiliate_links';
|
12 |
+
public $notification_interval = 25; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Build Notification
|
17 |
+
*
|
18 |
+
* @return array $notification notification is ready to add
|
19 |
+
*
|
20 |
+
* @since 7.12.3
|
21 |
+
*/
|
22 |
+
public function prepare_notification_data( $notification ) {
|
23 |
+
$affiliate_links = exactmetrics_get_option( 'affiliate_links', array() );
|
24 |
+
$no_new_links = false;
|
25 |
+
|
26 |
+
if ( is_array( $affiliate_links ) && ! empty( $affiliate_links ) ) {
|
27 |
+
if ( 2 === count( $affiliate_links ) && isset( $affiliate_links[0]['path'] ) && isset( $affiliate_links[1]['path'] ) ) {
|
28 |
+
$no_new_links = "/go/" === $affiliate_links[0]['path'] && "/recommend/" === $affiliate_links[1]['path'] ? true : false;
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
if ( true === $no_new_links || ( is_array( $affiliate_links ) && empty( $affiliate_links ) ) ) {
|
33 |
+
|
34 |
+
$notification['title'] = __( 'Set Up Affiliate Link Tracking', 'google-analytics-dashboard-for-wp' );
|
35 |
+
// Translators: Set up affiliate links notification content
|
36 |
+
$notification['content'] = sprintf( __( 'By tracking your affiliate links in Google Analytics, you can gather all the data you need to optimize your links for maximizing affiliate revenue. You can track affiliate link clicks on your website with little configuration needed.<br><br>%sIn this article%s, we’ll show you how to set up affiliate link tracking in WordPress.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/how-to-set-up-affiliate-link-tracking-in-wordpress/' ) . '" target="_blank">', '</a>' );
|
37 |
+
$notification['btns'] = array(
|
38 |
+
"read_more" => array(
|
39 |
+
'url' => $this->build_external_link( 'https://www.exactmetrics.com/how-to-set-up-affiliate-link-tracking-in-wordpress/' ),
|
40 |
+
'text' => __( 'Read More', 'google-analytics-dashboard-for-wp' ),
|
41 |
+
'is_external' => true,
|
42 |
+
),
|
43 |
+
);
|
44 |
+
|
45 |
+
return $notification;
|
46 |
+
}
|
47 |
+
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
|
51 |
+
}
|
52 |
+
|
53 |
+
// initialize the class
|
54 |
+
new ExactMetrics_Notification_To_Setup_Affiliate_Links();
|
includes/admin/notifications/notification-traffic-dropping.php
CHANGED
@@ -1,52 +1,52 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when the number of total sessions is less than the previous 30 days.
|
5 |
-
* Recurrence: 30 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Traffic_Dropping extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_traffic_dropping';
|
12 |
-
public $notification_interval = 30; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Build Notification
|
17 |
-
*
|
18 |
-
* @return array $notification notification is ready to add
|
19 |
-
*
|
20 |
-
* @since 7.12.3
|
21 |
-
*/
|
22 |
-
public function prepare_notification_data( $notification ) {
|
23 |
-
$data = array();
|
24 |
-
$report = $this->get_report();
|
25 |
-
$data['prev_sessions_difference'] = isset( $report['data']['infobox']['sessions']['prev'] ) ? $report['data']['infobox']['sessions']['prev'] : 0;
|
26 |
-
|
27 |
-
if ( ! empty( $data ) && $data['prev_sessions_difference'] < 0 ) {
|
28 |
-
$notification['title'] = __( 'Your Website Traffic Is Dropping', 'google-analytics-dashboard-for-wp' );
|
29 |
-
// Translators: Traffic dropping notification content
|
30 |
-
$notification['content'] = sprintf( __( 'Your website traffic is decreasing and that’s a reason to take action now. Less traffic means less opportunities to make your brand known, make relationships and ultimately sell your service or product. <br><br>Follow the marketing hacks of %sthis article%s to start growing your traffic again.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/marketing-hacks-guaranteed-to-grow-your-traffic/' ) . '" target="_blank">', '</a>' );
|
31 |
-
$notification['btns'] = array(
|
32 |
-
"learn_more" => array(
|
33 |
-
'url' => $this->build_external_link( 'https://www.exactmetrics.com/marketing-hacks-guaranteed-to-grow-your-traffic/' ),
|
34 |
-
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
35 |
-
'is_external' => true,
|
36 |
-
),
|
37 |
-
"view_report" => array(
|
38 |
-
'url' => $this->get_view_url( 'exactmetrics-report-overview', 'exactmetrics_reports' ),
|
39 |
-
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
40 |
-
),
|
41 |
-
);
|
42 |
-
|
43 |
-
return $notification;
|
44 |
-
}
|
45 |
-
|
46 |
-
return false;
|
47 |
-
}
|
48 |
-
|
49 |
-
}
|
50 |
-
|
51 |
-
// initialize the class
|
52 |
-
new ExactMetrics_Notification_Traffic_Dropping();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when the number of total sessions is less than the previous 30 days.
|
5 |
+
* Recurrence: 30 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Traffic_Dropping extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_traffic_dropping';
|
12 |
+
public $notification_interval = 30; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Build Notification
|
17 |
+
*
|
18 |
+
* @return array $notification notification is ready to add
|
19 |
+
*
|
20 |
+
* @since 7.12.3
|
21 |
+
*/
|
22 |
+
public function prepare_notification_data( $notification ) {
|
23 |
+
$data = array();
|
24 |
+
$report = $this->get_report();
|
25 |
+
$data['prev_sessions_difference'] = isset( $report['data']['infobox']['sessions']['prev'] ) ? $report['data']['infobox']['sessions']['prev'] : 0;
|
26 |
+
|
27 |
+
if ( ! empty( $data ) && $data['prev_sessions_difference'] < 0 ) {
|
28 |
+
$notification['title'] = __( 'Your Website Traffic Is Dropping', 'google-analytics-dashboard-for-wp' );
|
29 |
+
// Translators: Traffic dropping notification content
|
30 |
+
$notification['content'] = sprintf( __( 'Your website traffic is decreasing and that’s a reason to take action now. Less traffic means less opportunities to make your brand known, make relationships and ultimately sell your service or product. <br><br>Follow the marketing hacks of %sthis article%s to start growing your traffic again.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/marketing-hacks-guaranteed-to-grow-your-traffic/' ) . '" target="_blank">', '</a>' );
|
31 |
+
$notification['btns'] = array(
|
32 |
+
"learn_more" => array(
|
33 |
+
'url' => $this->build_external_link( 'https://www.exactmetrics.com/marketing-hacks-guaranteed-to-grow-your-traffic/' ),
|
34 |
+
'text' => __( 'Learn More', 'google-analytics-dashboard-for-wp' ),
|
35 |
+
'is_external' => true,
|
36 |
+
),
|
37 |
+
"view_report" => array(
|
38 |
+
'url' => $this->get_view_url( 'exactmetrics-report-overview', 'exactmetrics_reports' ),
|
39 |
+
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' )
|
40 |
+
),
|
41 |
+
);
|
42 |
+
|
43 |
+
return $notification;
|
44 |
+
}
|
45 |
+
|
46 |
+
return false;
|
47 |
+
}
|
48 |
+
|
49 |
+
}
|
50 |
+
|
51 |
+
// initialize the class
|
52 |
+
new ExactMetrics_Notification_Traffic_Dropping();
|
includes/admin/notifications/notification-upgrade-for-email-summaries.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when lite version activated
|
5 |
-
* Recurrence: 30 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Upgrade_For_Email_Summaries extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_upgrade_for_email_summaries';
|
12 |
-
public $notification_interval = 30; // in days
|
13 |
-
public $notification_type = array( 'lite' );
|
14 |
-
public $notification_icon = 'warning';
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Build Notification
|
18 |
-
*
|
19 |
-
* @return array $notification notification is ready to add
|
20 |
-
*
|
21 |
-
* @since 7.12.3
|
22 |
-
*/
|
23 |
-
public function prepare_notification_data( $notification ) {
|
24 |
-
$notification['title'] = __( 'Upgrade to ExactMetrics Pro to get weekly email reports', 'google-analytics-dashboard-for-wp' );
|
25 |
-
// Translators: upgrade for email summaries notification content
|
26 |
-
$notification['content'] = sprintf( __( 'Wouldn’t it be easy if you could get your website’s performance report in your email inbox every week? With our new feature, Email Summaries, you can now view all your important stats in a simple report that’s delivered straight to your inbox. <br><br>You get an overview of your site\'s performance without logging in to WordPress or going through different Analytics reports. %sUpgrade to ExactMetrics Pro%s to enable the Email Summaries feature.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>' );
|
27 |
-
$notification['btns'] = array(
|
28 |
-
"get_exactmetrics_pro" => array(
|
29 |
-
'url' => $this->get_upgrade_url(),
|
30 |
-
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
-
'is_external' => true,
|
32 |
-
),
|
33 |
-
);
|
34 |
-
|
35 |
-
return $notification;
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
// initialize the class
|
41 |
-
new ExactMetrics_Notification_Upgrade_For_Email_Summaries();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when lite version activated
|
5 |
+
* Recurrence: 30 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Upgrade_For_Email_Summaries extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_upgrade_for_email_summaries';
|
12 |
+
public $notification_interval = 30; // in days
|
13 |
+
public $notification_type = array( 'lite' );
|
14 |
+
public $notification_icon = 'warning';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Build Notification
|
18 |
+
*
|
19 |
+
* @return array $notification notification is ready to add
|
20 |
+
*
|
21 |
+
* @since 7.12.3
|
22 |
+
*/
|
23 |
+
public function prepare_notification_data( $notification ) {
|
24 |
+
$notification['title'] = __( 'Upgrade to ExactMetrics Pro to get weekly email reports', 'google-analytics-dashboard-for-wp' );
|
25 |
+
// Translators: upgrade for email summaries notification content
|
26 |
+
$notification['content'] = sprintf( __( 'Wouldn’t it be easy if you could get your website’s performance report in your email inbox every week? With our new feature, Email Summaries, you can now view all your important stats in a simple report that’s delivered straight to your inbox. <br><br>You get an overview of your site\'s performance without logging in to WordPress or going through different Analytics reports. %sUpgrade to ExactMetrics Pro%s to enable the Email Summaries feature.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>' );
|
27 |
+
$notification['btns'] = array(
|
28 |
+
"get_exactmetrics_pro" => array(
|
29 |
+
'url' => $this->get_upgrade_url(),
|
30 |
+
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
+
'is_external' => true,
|
32 |
+
),
|
33 |
+
);
|
34 |
+
|
35 |
+
return $notification;
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
+
// initialize the class
|
41 |
+
new ExactMetrics_Notification_Upgrade_For_Email_Summaries();
|
includes/admin/notifications/notification-upgrade-for-form-conversion.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when lite version activated
|
5 |
-
* Recurrence: 20 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Upgrade_For_Form_Conversion extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_upgrade_for_form_conversion';
|
12 |
-
public $notification_interval = 20; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'plus' );
|
14 |
-
public $notification_icon = 'warning';
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Build Notification
|
18 |
-
*
|
19 |
-
* @return array $notification notification is ready to add
|
20 |
-
*
|
21 |
-
* @since 7.12.3
|
22 |
-
*/
|
23 |
-
public function prepare_notification_data( $notification ) {
|
24 |
-
$notification['title'] = __( 'Upgrade to ExactMetrics Pro to Track Form Conversion', 'google-analytics-dashboard-for-wp' );
|
25 |
-
// Translators: upgrade for form conversion notification content
|
26 |
-
$notification['content'] = sprintf( __( 'Forms are one of the most important points of interaction on your website. When a visitor fills out a form on your site, they’re taking the next step in their customer journey. That’s why it’s so crucial that your WordPress forms are optimized for conversions. Upgrade to %sExactMetrics Pro%s to track %sform conversions in Google Analytics.%s', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>', '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/addon/forms/' ) . '" target="_blank">', '</a>' );
|
27 |
-
$notification['btns'] = array(
|
28 |
-
"get_exactmetrics_pro" => array(
|
29 |
-
'url' => $this->get_upgrade_url(),
|
30 |
-
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
-
'is_external' => true,
|
32 |
-
),
|
33 |
-
);
|
34 |
-
|
35 |
-
return $notification;
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
// initialize the class
|
41 |
-
new ExactMetrics_Notification_Upgrade_For_Form_Conversion();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when lite version activated
|
5 |
+
* Recurrence: 20 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Upgrade_For_Form_Conversion extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_upgrade_for_form_conversion';
|
12 |
+
public $notification_interval = 20; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'plus' );
|
14 |
+
public $notification_icon = 'warning';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Build Notification
|
18 |
+
*
|
19 |
+
* @return array $notification notification is ready to add
|
20 |
+
*
|
21 |
+
* @since 7.12.3
|
22 |
+
*/
|
23 |
+
public function prepare_notification_data( $notification ) {
|
24 |
+
$notification['title'] = __( 'Upgrade to ExactMetrics Pro to Track Form Conversion', 'google-analytics-dashboard-for-wp' );
|
25 |
+
// Translators: upgrade for form conversion notification content
|
26 |
+
$notification['content'] = sprintf( __( 'Forms are one of the most important points of interaction on your website. When a visitor fills out a form on your site, they’re taking the next step in their customer journey. That’s why it’s so crucial that your WordPress forms are optimized for conversions. Upgrade to %sExactMetrics Pro%s to track %sform conversions in Google Analytics.%s', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>', '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/addon/forms/' ) . '" target="_blank">', '</a>' );
|
27 |
+
$notification['btns'] = array(
|
28 |
+
"get_exactmetrics_pro" => array(
|
29 |
+
'url' => $this->get_upgrade_url(),
|
30 |
+
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
+
'is_external' => true,
|
32 |
+
),
|
33 |
+
);
|
34 |
+
|
35 |
+
return $notification;
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
+
// initialize the class
|
41 |
+
new ExactMetrics_Notification_Upgrade_For_Form_Conversion();
|
includes/admin/notifications/notification-upgrade-for-google-optimize.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when lite, plus version activated
|
5 |
-
* Recurrence: 30 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Upgrade_For_Google_Optimize extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_upgrade_for_google_optimize';
|
12 |
-
public $notification_interval = 30; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'plus' );
|
14 |
-
public $notification_icon = 'warning';
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Build Notification
|
18 |
-
*
|
19 |
-
* @return array $notification notification is ready to add
|
20 |
-
*
|
21 |
-
* @since 7.12.3
|
22 |
-
*/
|
23 |
-
public function prepare_notification_data( $notification ) {
|
24 |
-
$notification['title'] = __( 'Upgrade to ExactMetrics Pro to Enable Google Optimize', 'google-analytics-dashboard-for-wp' );
|
25 |
-
// Translators: upgrade for google optimize notification content
|
26 |
-
$notification['content'] = sprintf( __( '%sGoogle Optimize%s is a free A/B testing and personalization product by Google that lets you easily conduct experiments to see what works best on your site. With Google Optimize, you can use split testing and personalization to create online experiences that engage and delight your customers. %sUpgrade to ExactMetrics Pro%s to unlock the Google Optimize addon.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/addon/google-optimize/' ) . '" target="_blank">', '</a>', '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>' );
|
27 |
-
$notification['btns'] = array(
|
28 |
-
"get_exactmetrics_pro" => array(
|
29 |
-
'url' => $this->get_upgrade_url(),
|
30 |
-
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
-
'is_external' => true,
|
32 |
-
),
|
33 |
-
);
|
34 |
-
|
35 |
-
return $notification;
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
// initialize the class
|
41 |
-
new ExactMetrics_Notification_Upgrade_For_Google_Optimize();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when lite, plus version activated
|
5 |
+
* Recurrence: 30 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Upgrade_For_Google_Optimize extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_upgrade_for_google_optimize';
|
12 |
+
public $notification_interval = 30; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'plus' );
|
14 |
+
public $notification_icon = 'warning';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Build Notification
|
18 |
+
*
|
19 |
+
* @return array $notification notification is ready to add
|
20 |
+
*
|
21 |
+
* @since 7.12.3
|
22 |
+
*/
|
23 |
+
public function prepare_notification_data( $notification ) {
|
24 |
+
$notification['title'] = __( 'Upgrade to ExactMetrics Pro to Enable Google Optimize', 'google-analytics-dashboard-for-wp' );
|
25 |
+
// Translators: upgrade for google optimize notification content
|
26 |
+
$notification['content'] = sprintf( __( '%sGoogle Optimize%s is a free A/B testing and personalization product by Google that lets you easily conduct experiments to see what works best on your site. With Google Optimize, you can use split testing and personalization to create online experiences that engage and delight your customers. %sUpgrade to ExactMetrics Pro%s to unlock the Google Optimize addon.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/addon/google-optimize/' ) . '" target="_blank">', '</a>', '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>' );
|
27 |
+
$notification['btns'] = array(
|
28 |
+
"get_exactmetrics_pro" => array(
|
29 |
+
'url' => $this->get_upgrade_url(),
|
30 |
+
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
+
'is_external' => true,
|
32 |
+
),
|
33 |
+
);
|
34 |
+
|
35 |
+
return $notification;
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
+
// initialize the class
|
41 |
+
new ExactMetrics_Notification_Upgrade_For_Google_Optimize();
|
includes/admin/notifications/notification-upgrade-for-search-console.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification when lite version activated
|
5 |
-
* Recurrence: 30 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Upgrade_For_Search_Console extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_upgrade_for_search_console_report';
|
12 |
-
public $notification_interval = 30; // in days
|
13 |
-
public $notification_type = array( 'lite' );
|
14 |
-
public $notification_icon = 'warning';
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Build Notification
|
18 |
-
*
|
19 |
-
* @return array $notification notification is ready to add
|
20 |
-
*
|
21 |
-
* @since 7.12.3
|
22 |
-
*/
|
23 |
-
public function prepare_notification_data( $notification ) {
|
24 |
-
$notification['title'] = __( 'Get access to Google Search Keywords data by upgrading to ExactMetrics Pro', 'google-analytics-dashboard-for-wp' );
|
25 |
-
// Translators: upgrade for search console notification content
|
26 |
-
$notification['content'] = sprintf( __( 'Do you want to find out which search terms from Google bring your site the most visitors? %sUpgrade to ExactMetrics PRO%s today and get access to the %sSearch Console Report%s and more directly in your WordPress admin.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>', '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/feature/search-console-report/' ) . '" target="_blank">', '</a>' );
|
27 |
-
$notification['btns'] = array(
|
28 |
-
"get_exactmetrics_pro" => array(
|
29 |
-
'url' => $this->get_upgrade_url(),
|
30 |
-
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
-
'is_external' => true,
|
32 |
-
),
|
33 |
-
);
|
34 |
-
|
35 |
-
return $notification;
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
// initialize the class
|
41 |
-
new ExactMetrics_Notification_Upgrade_For_Search_Console();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification when lite version activated
|
5 |
+
* Recurrence: 30 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Upgrade_For_Search_Console extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_upgrade_for_search_console_report';
|
12 |
+
public $notification_interval = 30; // in days
|
13 |
+
public $notification_type = array( 'lite' );
|
14 |
+
public $notification_icon = 'warning';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Build Notification
|
18 |
+
*
|
19 |
+
* @return array $notification notification is ready to add
|
20 |
+
*
|
21 |
+
* @since 7.12.3
|
22 |
+
*/
|
23 |
+
public function prepare_notification_data( $notification ) {
|
24 |
+
$notification['title'] = __( 'Get access to Google Search Keywords data by upgrading to ExactMetrics Pro', 'google-analytics-dashboard-for-wp' );
|
25 |
+
// Translators: upgrade for search console notification content
|
26 |
+
$notification['content'] = sprintf( __( 'Do you want to find out which search terms from Google bring your site the most visitors? %sUpgrade to ExactMetrics PRO%s today and get access to the %sSearch Console Report%s and more directly in your WordPress admin.', 'google-analytics-dashboard-for-wp' ), '<a href="' . $this->get_upgrade_url() . '" target="_blank">', '</a>', '<a href="' . $this->build_external_link( 'https://www.exactmetrics.com/feature/search-console-report/' ) . '" target="_blank">', '</a>' );
|
27 |
+
$notification['btns'] = array(
|
28 |
+
"get_exactmetrics_pro" => array(
|
29 |
+
'url' => $this->get_upgrade_url(),
|
30 |
+
'text' => __( 'Get ExactMetrics Pro', 'google-analytics-dashboard-for-wp' ),
|
31 |
+
'is_external' => true,
|
32 |
+
),
|
33 |
+
);
|
34 |
+
|
35 |
+
return $notification;
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
+
// initialize the class
|
41 |
+
new ExactMetrics_Notification_Upgrade_For_Search_Console();
|
includes/admin/notifications/notification-upgrade-to-pro.php
CHANGED
@@ -1,42 +1,42 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add notification after 1 week of lite version installation
|
5 |
-
* Recurrence: 40 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Upgrade_To_Pro extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_upgrade_to_pro';
|
12 |
-
public $notification_interval = 40; // in days
|
13 |
-
public $notification_first_run_time = '+7 day';
|
14 |
-
public $notification_type = array( 'lite' );
|
15 |
-
public $notification_icon = 'star';
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Build Notification
|
19 |
-
*
|
20 |
-
* @return array $notification notification is ready to add
|
21 |
-
*
|
22 |
-
* @since 7.12.3
|
23 |
-
*/
|
24 |
-
public function prepare_notification_data( $notification ) {
|
25 |
-
$notification['title'] = __( 'Upgrade to ExactMetrics Pro and unlock advanced tracking and reports', 'google-analytics-dashboard-for-wp' );
|
26 |
-
// Translators: upgrade to pro notification content
|
27 |
-
$notification['content'] = __( 'By upgrading to ExactMetrics Pro you get access to additional reports right in your WordPress dashboard and advanced tracking features like eCommerce, Custom Dimensions, Forms tracking and more!', 'google-analytics-dashboard-for-wp' );
|
28 |
-
$notification['btns'] = array(
|
29 |
-
"upgrade_to_pro" => array(
|
30 |
-
'url' => $this->get_upgrade_url(),
|
31 |
-
'text' => __( 'Upgrade to Pro', 'google-analytics-dashboard-for-wp' ),
|
32 |
-
'is_external' => true,
|
33 |
-
),
|
34 |
-
);
|
35 |
-
|
36 |
-
return $notification;
|
37 |
-
}
|
38 |
-
|
39 |
-
}
|
40 |
-
|
41 |
-
// initialize the class
|
42 |
-
new ExactMetrics_Notification_Upgrade_To_Pro();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add notification after 1 week of lite version installation
|
5 |
+
* Recurrence: 40 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Upgrade_To_Pro extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_upgrade_to_pro';
|
12 |
+
public $notification_interval = 40; // in days
|
13 |
+
public $notification_first_run_time = '+7 day';
|
14 |
+
public $notification_type = array( 'lite' );
|
15 |
+
public $notification_icon = 'star';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Build Notification
|
19 |
+
*
|
20 |
+
* @return array $notification notification is ready to add
|
21 |
+
*
|
22 |
+
* @since 7.12.3
|
23 |
+
*/
|
24 |
+
public function prepare_notification_data( $notification ) {
|
25 |
+
$notification['title'] = __( 'Upgrade to ExactMetrics Pro and unlock advanced tracking and reports', 'google-analytics-dashboard-for-wp' );
|
26 |
+
// Translators: upgrade to pro notification content
|
27 |
+
$notification['content'] = __( 'By upgrading to ExactMetrics Pro you get access to additional reports right in your WordPress dashboard and advanced tracking features like eCommerce, Custom Dimensions, Forms tracking and more!', 'google-analytics-dashboard-for-wp' );
|
28 |
+
$notification['btns'] = array(
|
29 |
+
"upgrade_to_pro" => array(
|
30 |
+
'url' => $this->get_upgrade_url(),
|
31 |
+
'text' => __( 'Upgrade to Pro', 'google-analytics-dashboard-for-wp' ),
|
32 |
+
'is_external' => true,
|
33 |
+
),
|
34 |
+
);
|
35 |
+
|
36 |
+
return $notification;
|
37 |
+
}
|
38 |
+
|
39 |
+
}
|
40 |
+
|
41 |
+
// initialize the class
|
42 |
+
new ExactMetrics_Notification_Upgrade_To_Pro();
|
includes/admin/notifications/notification-visitors.php
CHANGED
@@ -1,50 +1,50 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Add visitors notification
|
5 |
-
* Recurrence: 30 Days
|
6 |
-
*
|
7 |
-
* @since 7.12.3
|
8 |
-
*/
|
9 |
-
final class ExactMetrics_Notification_Visitors extends ExactMetrics_Notification_Event {
|
10 |
-
|
11 |
-
public $notification_id = 'exactmetrics_notification_visitors';
|
12 |
-
public $notification_interval = 30; // in days
|
13 |
-
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
-
public $notification_icon = 'lightning';
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Build Notification
|
18 |
-
*
|
19 |
-
* @param array $report Overview report
|
20 |
-
*
|
21 |
-
* @return array $notification notification is ready to add
|
22 |
-
*
|
23 |
-
* @since 7.12.3
|
24 |
-
*/
|
25 |
-
public function prepare_notification_data( $notification ) {
|
26 |
-
$report = $this->get_report();
|
27 |
-
|
28 |
-
if ( ! is_array( $report ) || empty( $report ) ) {
|
29 |
-
return false;
|
30 |
-
}
|
31 |
-
|
32 |
-
$total_visitors = isset( $report['data']['infobox']['sessions']['value'] ) ? $report['data']['infobox']['sessions']['value'] : 0;
|
33 |
-
// Translators: visitors notification title
|
34 |
-
$notification['title'] = sprintf( __( 'See how %s visitors found your site!', 'google-analytics-dashboard-for-wp' ), $total_visitors );
|
35 |
-
// Translators: visitors notification content
|
36 |
-
$notification['content'] = sprintf( __( 'Your website has been visited by %s visitors in the past 30 days. Click the button below to view the full analytics report.', 'google-analytics-dashboard-for-wp' ), $total_visitors );
|
37 |
-
$notification['btns'] = array(
|
38 |
-
"view_report" => array(
|
39 |
-
'url' => $this->get_view_url( 'exactmetrics-report-overview', 'exactmetrics_reports' ),
|
40 |
-
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' ),
|
41 |
-
),
|
42 |
-
);
|
43 |
-
|
44 |
-
return $notification;
|
45 |
-
}
|
46 |
-
|
47 |
-
}
|
48 |
-
|
49 |
-
// initialize the class
|
50 |
-
new ExactMetrics_Notification_Visitors();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add visitors notification
|
5 |
+
* Recurrence: 30 Days
|
6 |
+
*
|
7 |
+
* @since 7.12.3
|
8 |
+
*/
|
9 |
+
final class ExactMetrics_Notification_Visitors extends ExactMetrics_Notification_Event {
|
10 |
+
|
11 |
+
public $notification_id = 'exactmetrics_notification_visitors';
|
12 |
+
public $notification_interval = 30; // in days
|
13 |
+
public $notification_type = array( 'basic', 'lite', 'master', 'plus', 'pro' );
|
14 |
+
public $notification_icon = 'lightning';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Build Notification
|
18 |
+
*
|
19 |
+
* @param array $report Overview report
|
20 |
+
*
|
21 |
+
* @return array $notification notification is ready to add
|
22 |
+
*
|
23 |
+
* @since 7.12.3
|
24 |
+
*/
|
25 |
+
public function prepare_notification_data( $notification ) {
|
26 |
+
$report = $this->get_report();
|
27 |
+
|
28 |
+
if ( ! is_array( $report ) || empty( $report ) ) {
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
|
32 |
+
$total_visitors = isset( $report['data']['infobox']['sessions']['value'] ) ? $report['data']['infobox']['sessions']['value'] : 0;
|
33 |
+
// Translators: visitors notification title
|
34 |
+
$notification['title'] = sprintf( __( 'See how %s visitors found your site!', 'google-analytics-dashboard-for-wp' ), $total_visitors );
|
35 |
+
// Translators: visitors notification content
|
36 |
+
$notification['content'] = sprintf( __( 'Your website has been visited by %s visitors in the past 30 days. Click the button below to view the full analytics report.', 'google-analytics-dashboard-for-wp' ), $total_visitors );
|
37 |
+
$notification['btns'] = array(
|
38 |
+
"view_report" => array(
|
39 |
+
'url' => $this->get_view_url( 'exactmetrics-report-overview', 'exactmetrics_reports' ),
|
40 |
+
'text' => __( 'View Report', 'google-analytics-dashboard-for-wp' ),
|
41 |
+
),
|
42 |
+
);
|
43 |
+
|
44 |
+
return $notification;
|
45 |
+
}
|
46 |
+
|
47 |
+
}
|
48 |
+
|
49 |
+
// initialize the class
|
50 |
+
new ExactMetrics_Notification_Visitors();
|
includes/admin/sharedcount.php
CHANGED
@@ -1,637 +1,637 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Handles the SharedCount integration and count grabbing.
|
5 |
-
*
|
6 |
-
* Class ExactMetrics_SharedCount
|
7 |
-
*/
|
8 |
-
class ExactMetrics_SharedCount {
|
9 |
-
|
10 |
-
/**
|
11 |
-
* The action used to schedule daily events.
|
12 |
-
*
|
13 |
-
* @var string
|
14 |
-
*/
|
15 |
-
public $cron_key = 'exactmetrics_sharedcount_daily_update';
|
16 |
-
/**
|
17 |
-
* Index progress key.
|
18 |
-
*
|
19 |
-
* @var string
|
20 |
-
*/
|
21 |
-
public static $progress_key = 'exactmetrics_sharedcount_index_progress';
|
22 |
-
/**
|
23 |
-
* Index progress.
|
24 |
-
*
|
25 |
-
* @var array
|
26 |
-
*/
|
27 |
-
public static $progress;
|
28 |
-
/**
|
29 |
-
* The error message from the api call.
|
30 |
-
*
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
public $error;
|
34 |
-
/**
|
35 |
-
* The API endpoint.
|
36 |
-
*
|
37 |
-
* @var string
|
38 |
-
*/
|
39 |
-
private $endpoint = 'https://api.sharedcount.com/v1.0/';
|
40 |
-
/**
|
41 |
-
* The API key to use for the requests.
|
42 |
-
*
|
43 |
-
* @var string
|
44 |
-
*/
|
45 |
-
private $api_key;
|
46 |
-
/**
|
47 |
-
* If the current query needs to run again.
|
48 |
-
*
|
49 |
-
* @var bool
|
50 |
-
*/
|
51 |
-
private $more_pages = false;
|
52 |
-
|
53 |
-
/**
|
54 |
-
* ExactMetrics_SharedCount constructor.
|
55 |
-
*/
|
56 |
-
public function __construct() {
|
57 |
-
|
58 |
-
add_action( 'wp_ajax_exactmetrics_sharedcount_start_indexing', array( $this, 'ajax_start_indexing' ) );
|
59 |
-
add_action( 'wp_ajax_exactmetrics_sharedcount_get_index_progress', array(
|
60 |
-
$this,
|
61 |
-
'ajax_get_index_progress'
|
62 |
-
) );
|
63 |
-
|
64 |
-
add_action( 'exactmetrics_sharedcount_get_more_posts', array( $this, 'get_more_counts' ) );
|
65 |
-
|
66 |
-
add_action( 'exactmetrics_sharedcount_bulk_grab', array( $this, 'grab_and_store_bulk_by_id' ), 10, 2 );
|
67 |
-
|
68 |
-
add_action( $this->cron_key, array( $this, 'daily_cron_update' ) );
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* AJAX handler from the Vue app that checks if the API key is set and handles
|
73 |
-
* an error message from the SharedCount API call. If the first call is successful it will schedule
|
74 |
-
* a daily cron to keep the counts fresh.
|
75 |
-
*/
|
76 |
-
public function ajax_start_indexing() {
|
77 |
-
|
78 |
-
check_ajax_referer( 'mi-admin-nonce', 'nonce' );
|
79 |
-
|
80 |
-
if ( $this->get_api_key() ) {
|
81 |
-
if ( $this->start_posts_count() ) {
|
82 |
-
$this->schedule_daily_update();
|
83 |
-
wp_send_json_success( array(
|
84 |
-
'max_pages' => $this->more_pages,
|
85 |
-
) );
|
86 |
-
} else {
|
87 |
-
wp_send_json_error( array(
|
88 |
-
'message' => $this->error,
|
89 |
-
) );
|
90 |
-
}
|
91 |
-
}
|
92 |
-
|
93 |
-
// No API key, let's send an error message.
|
94 |
-
wp_send_json_error( array(
|
95 |
-
'message' => esc_html__( 'The SharedCount API key is not set', 'google-analytics-dashboard-for-wp' ),
|
96 |
-
) );
|
97 |
-
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Get the API key.
|
102 |
-
*
|
103 |
-
* @return string
|
104 |
-
*/
|
105 |
-
public function get_api_key() {
|
106 |
-
|
107 |
-
if ( empty( $this->api_key ) ) {
|
108 |
-
$this->api_key = exactmetrics_get_option( 'sharedcount_key' );
|
109 |
-
}
|
110 |
-
|
111 |
-
return $this->api_key;
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Start a grabbing process that will schedule events to grab more pages if needed.
|
116 |
-
*
|
117 |
-
* @return bool
|
118 |
-
*/
|
119 |
-
public function start_posts_count() {
|
120 |
-
|
121 |
-
return $this->get_more_counts( 1 );
|
122 |
-
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Handler for the scheduled event to grab more data for sites with large number of posts.
|
127 |
-
* This is also used by the first call and uses the return value to determine if an error was encountered.
|
128 |
-
* The error gets set in the $error property and used for display.
|
129 |
-
*
|
130 |
-
* @param int $page The page number to grab counts for.
|
131 |
-
*
|
132 |
-
* @return bool
|
133 |
-
*/
|
134 |
-
public function get_more_counts( $page ) {
|
135 |
-
|
136 |
-
$urls = $this->get_post_urls( $page );
|
137 |
-
$urls_as_keys = $this->urls_as_keys( $urls );
|
138 |
-
|
139 |
-
if ( $this->use_bulk_api() ) {
|
140 |
-
$bulk_request = $this->post_bulk_urls( $urls );
|
141 |
-
|
142 |
-
if ( $bulk_request && ! empty( $bulk_request['bulk_id'] ) ) {
|
143 |
-
$this->grab_and_store_bulk_by_id( $bulk_request['bulk_id'], $urls_as_keys );
|
144 |
-
} else {
|
145 |
-
return false;
|
146 |
-
}
|
147 |
-
} else {
|
148 |
-
$store_counts = $this->grab_counts_one_by_one( $urls );
|
149 |
-
if ( ! $store_counts ) {
|
150 |
-
// Error encountered, return error.
|
151 |
-
return false;
|
152 |
-
}
|
153 |
-
}
|
154 |
-
|
155 |
-
$this->save_progress( $page, $this->more_pages );
|
156 |
-
|
157 |
-
if ( $this->more_pages ) {
|
158 |
-
$page ++;
|
159 |
-
$this->schedule_next_page( $page );
|
160 |
-
}
|
161 |
-
|
162 |
-
return true;
|
163 |
-
|
164 |
-
}
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Save the current indexing progress.
|
168 |
-
*
|
169 |
-
* @param int $page The current page.
|
170 |
-
* @param int $max_pages The total number of pages.
|
171 |
-
*/
|
172 |
-
public function save_progress( $page, $max_pages ) {
|
173 |
-
update_option( self::$progress_key, array(
|
174 |
-
'page' => $page,
|
175 |
-
'max_pages' => $max_pages,
|
176 |
-
), false );
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* Reset the progress option. Used for when the cron is disabled.
|
181 |
-
*/
|
182 |
-
public function reset_progress() {
|
183 |
-
delete_option( self::$progress_key );
|
184 |
-
}
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Use WP_Query to get a list of URLs to query SharedCount for share data.
|
188 |
-
*
|
189 |
-
* @param int $page The page number.
|
190 |
-
*
|
191 |
-
* @return array
|
192 |
-
*/
|
193 |
-
public function get_post_urls( $page = 1 ) {
|
194 |
-
|
195 |
-
$posts_args = array(
|
196 |
-
'posts_per_page' => 100, // Don't try to load more than 500 posts at once.
|
197 |
-
'fields' => 'ids', // Load just the ids.
|
198 |
-
'paged' => $page,
|
199 |
-
'suppress_filters' => true, // Avoid loading additional functionality from other plugins/theme.
|
200 |
-
);
|
201 |
-
$posts_query = new WP_Query( $posts_args );
|
202 |
-
$urls = array();
|
203 |
-
|
204 |
-
if ( $posts_query->have_posts() ) {
|
205 |
-
while ( $posts_query->have_posts() ) {
|
206 |
-
$posts_query->the_post();
|
207 |
-
|
208 |
-
$urls[ get_the_ID() ] = get_permalink( get_the_ID() );
|
209 |
-
}
|
210 |
-
}
|
211 |
-
|
212 |
-
if ( $posts_query->max_num_pages > $page ) {
|
213 |
-
$this->more_pages = $posts_query->max_num_pages;
|
214 |
-
} else {
|
215 |
-
$this->more_pages = false;
|
216 |
-
}
|
217 |
-
|
218 |
-
wp_reset_postdata();
|
219 |
-
|
220 |
-
return $urls;
|
221 |
-
}
|
222 |
-
|
223 |
-
/**
|
224 |
-
* Use URLs as array keys to make it easier to match with the post id.
|
225 |
-
*
|
226 |
-
* @param array $urls The urls with post ids as keys.
|
227 |
-
*
|
228 |
-
* @return array
|
229 |
-
*/
|
230 |
-
public function urls_as_keys( $urls ) {
|
231 |
-
|
232 |
-
$urls_as_keys = array();
|
233 |
-
foreach ( $urls as $id => $url ) {
|
234 |
-
$urls_as_keys[ $url ] = $id;
|
235 |
-
}
|
236 |
-
|
237 |
-
return $urls_as_keys;
|
238 |
-
|
239 |
-
}
|
240 |
-
|
241 |
-
/**
|
242 |
-
* Helper method for using the bulk API. Disabled by default as the free api doesn't have access to it.
|
243 |
-
* This can be used by large sites to use less requests to the SharedCount API and grab data more efficiently
|
244 |
-
* if they have a paid license.
|
245 |
-
*
|
246 |
-
* @return mixed|void
|
247 |
-
*/
|
248 |
-
public function use_bulk_api() {
|
249 |
-
// Bulk API is not available for free sharedcount accounts so let's set this to off by default.
|
250 |
-
return apply_filters( 'exactmetrics_sharedcount_use_bulk_api', false );
|
251 |
-
}
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Use the bulk API method to post data to the SharedCount API.
|
255 |
-
*
|
256 |
-
* @param array $urls An array with the URLs to be sent in the bulk request.
|
257 |
-
*
|
258 |
-
* @return bool|mixed
|
259 |
-
*/
|
260 |
-
public function post_bulk_urls( $urls ) {
|
261 |
-
|
262 |
-
$body = implode( "\n", $urls );
|
263 |
-
|
264 |
-
$request_url = add_query_arg(
|
265 |
-
array(
|
266 |
-
'apikey' => $this->get_api_key(),
|
267 |
-
),
|
268 |
-
$this->get_api_url( 'bulk' )
|
269 |
-
);
|
270 |
-
|
271 |
-
$request = wp_remote_post( $request_url, array(
|
272 |
-
'body' => $body,
|
273 |
-
) );
|
274 |
-
|
275 |
-
$response = wp_remote_retrieve_body( $request );
|
276 |
-
$parsed_response = json_decode( $response, true );
|
277 |
-
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
|
278 |
-
return $parsed_response;
|
279 |
-
} else {
|
280 |
-
$this->handle_api_error( $parsed_response );
|
281 |
-
|
282 |
-
return false;
|
283 |
-
}
|
284 |
-
}
|
285 |
-
|
286 |
-
/**
|
287 |
-
* Get the API url.
|
288 |
-
*
|
289 |
-
* @param string $path The API path to use e.g. "bulk".
|
290 |
-
*
|
291 |
-
* @return string
|
292 |
-
*/
|
293 |
-
public function get_api_url( $path = '' ) {
|
294 |
-
// Allow users to override the SharedCount URL if they have a custom URL.
|
295 |
-
return apply_filters( 'exactmetrics_sharedcount_api_url', $this->endpoint . $path );
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Generic handler for error responses from the SharedCount API.
|
300 |
-
* This uses the $error property to pass the error back for being displayed.
|
301 |
-
*
|
302 |
-
* @param array $parsed_response The response object from a SharedCount API call converted to an Array.
|
303 |
-
*/
|
304 |
-
public function handle_api_error( $parsed_response ) {
|
305 |
-
if ( isset( $parsed_response['Error'] ) && isset( $parsed_response['Type'] ) && 'invalid_api_key' === $parsed_response['Type'] ) {
|
306 |
-
$error = esc_html__( 'The SharedCount API key is invalid', 'google-analytics-dashboard-for-wp' );
|
307 |
-
} elseif ( ! empty( $parsed_response['quota_exceeded'] ) ) {
|
308 |
-
$error = $parsed_response['quota_exceeded'];
|
309 |
-
} else {
|
310 |
-
$error = isset( $parsed_response['Error'] ) ? $parsed_response['Error'] : esc_html__( 'There was an error grabbing data from SharedCount, please check the API Key', 'google-analytics-dashboard-for-wp' );
|
311 |
-
}
|
312 |
-
$this->error = $error;
|
313 |
-
}
|
314 |
-
|
315 |
-
/**
|
316 |
-
* Attempt to grab bulk data from the API by bulk id, if the bulk request is not completed
|
317 |
-
* schedule an event to try again in a minute.
|
318 |
-
*
|
319 |
-
* @param string $bulk_id The bulk id from the SharedCount bulk post request.
|
320 |
-
* @param array $urls_as_keys An array of URLs where the keys are the URLs and the values are the post ids.
|
321 |
-
*/
|
322 |
-
public function grab_and_store_bulk_by_id( $bulk_id, $urls_as_keys ) {
|
323 |
-
$bulk_data = $this->get_bulk_data( $bulk_id );
|
324 |
-
// If the processing for the current bulk id is not completed schedule a single event to try again.
|
325 |
-
if ( $bulk_data['_meta']['completed'] ) {
|
326 |
-
$this->store_bulk_data( $bulk_data, $urls_as_keys );
|
327 |
-
} else {
|
328 |
-
$this->schedule_bulk_grabbing( $bulk_id, $urls_as_keys );
|
329 |
-
}
|
330 |
-
}
|
331 |
-
|
332 |
-
/**
|
333 |
-
* Grab data from the SharedCount API using their Bulk API.
|
334 |
-
*
|
335 |
-
* @param string $bulk_id The bulk id from a POST request to the bulk API.
|
336 |
-
*
|
337 |
-
* @return bool|mixed
|
338 |
-
* @see ExactMetrics_SharedCount::post_bulk_urls()
|
339 |
-
*
|
340 |
-
*/
|
341 |
-
public function get_bulk_data( $bulk_id ) {
|
342 |
-
|
343 |
-
$request_url = add_query_arg(
|
344 |
-
array(
|
345 |
-
'bulk_id' => $bulk_id,
|
346 |
-
'apikey' => $this->get_api_key(),
|
347 |
-
),
|
348 |
-
$this->get_api_url()
|
349 |
-
);
|
350 |
-
|
351 |
-
$request = wp_remote_get( $request_url );
|
352 |
-
|
353 |
-
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
|
354 |
-
$response = wp_remote_retrieve_body( $request );
|
355 |
-
$parsed_response = json_decode( $response, true );
|
356 |
-
|
357 |
-
return $parsed_response;
|
358 |
-
} else {
|
359 |
-
return false;
|
360 |
-
}
|
361 |
-
}
|
362 |
-
|
363 |
-
/**
|
364 |
-
* Iterate through the bulk data returned and store it in the post meta.
|
365 |
-
*
|
366 |
-
* @param array $bulk_data The bulk data response from the SharedCount API.
|
367 |
-
* @param array $urls_as_keys An array of URLs where the keys are the URLs and the values are the post ids.
|
368 |
-
*/
|
369 |
-
public function store_bulk_data( $bulk_data, $urls_as_keys ) {
|
370 |
-
if ( ! empty( $bulk_data['data'] ) && is_array( $bulk_data['data'] ) ) {
|
371 |
-
foreach ( $bulk_data['data'] as $url => $values ) {
|
372 |
-
$post_id = array_key_exists( $url, $urls_as_keys ) ? $urls_as_keys[ $url ] : false;
|
373 |
-
|
374 |
-
if ( $post_id ) {
|
375 |
-
$this->store_post_counts( $post_id, $values );
|
376 |
-
}
|
377 |
-
}
|
378 |
-
}
|
379 |
-
}
|
380 |
-
|
381 |
-
/**
|
382 |
-
* Save the post counts response to the post meta.
|
383 |
-
* The total value is saved separately for querying.
|
384 |
-
*
|
385 |
-
* @param int $post_id The post id to save to.
|
386 |
-
* @param array $values The array of values received from the SharedCount API.
|
387 |
-
*
|
388 |
-
* @see ExactMetrics_SharedCount::get_counts_by_url()
|
389 |
-
*/
|
390 |
-
public function store_post_counts( $post_id, $values ) {
|
391 |
-
$total_count = $this->combine_counts( $values );
|
392 |
-
update_post_meta( $post_id, '_exactmetrics_sharedcount_total', $total_count );
|
393 |
-
update_post_meta( $post_id, '_exactmetrics_sharedcount_values', $values );
|
394 |
-
}
|
395 |
-
|
396 |
-
/**
|
397 |
-
* Process a SharedCounts response and compile all counts into one number.
|
398 |
-
*
|
399 |
-
* @param array $response Array from decoding the API JSON response.
|
400 |
-
*
|
401 |
-
* @return int
|
402 |
-
*/
|
403 |
-
public function combine_counts( $response ) {
|
404 |
-
|
405 |
-
$total = 0;
|
406 |
-
if ( ! isset( $response['Error'] ) ) {
|
407 |
-
foreach ( $response as $count ) {
|
408 |
-
if ( is_int( $count ) ) {
|
409 |
-
$total += $count;
|
410 |
-
} elseif ( is_array( $count ) && isset( $count['share_count'] ) ) {
|
411 |
-
$total += $count['share_count'];
|
412 |
-
}
|
413 |
-
}
|
414 |
-
}
|
415 |
-
|
416 |
-
return $total;
|
417 |
-
}
|
418 |
-
|
419 |
-
/**
|
420 |
-
* If the bulk request is not completed we need to schedule it to try again later.
|
421 |
-
*
|
422 |
-
* @param string $bulk_id The bulk id from the SharedCount bulk post request.
|
423 |
-
* @param array $urls_as_keys An array of URLs where the keys are the URLs and the values are the post ids.
|
424 |
-
*
|
425 |
-
* @see ExactMetrics_SharedCount::post_bulk_urls()
|
426 |
-
* @see ExactMetrics_SharedCount::grab_and_store_bulk_by_id()
|
427 |
-
*/
|
428 |
-
public function schedule_bulk_grabbing( $bulk_id, $urls_as_keys ) {
|
429 |
-
|
430 |
-
wp_schedule_single_event( time() + 60, 'exactmetrics_sharedcount_bulk_grab', array(
|
431 |
-
'bulk_id' => $bulk_id,
|
432 |
-
'urls' => $urls_as_keys,
|
433 |
-
) );
|
434 |
-
|
435 |
-
}
|
436 |
-
|
437 |
-
/**
|
438 |
-
* The SharedCount Bulk API is not available for free users so we need
|
439 |
-
* to use multiple calls to the API to grab data.
|
440 |
-
*
|
441 |
-
* @param array $urls An array of urls with the post ids as keys.
|
442 |
-
*
|
443 |
-
* @return bool
|
444 |
-
* @see ExactMetrics_SharedCount::get_post_urls()
|
445 |
-
*
|
446 |
-
*/
|
447 |
-
private function grab_counts_one_by_one( $urls ) {
|
448 |
-
|
449 |
-
foreach ( $urls as $id => $url ) {
|
450 |
-
$counts = $this->get_counts_by_url( $url );
|
451 |
-
|
452 |
-
if ( $counts ) {
|
453 |
-
$this->store_post_counts( $id, $counts );
|
454 |
-
} else {
|
455 |
-
// Return false to display error message from API request.
|
456 |
-
return false;
|
457 |
-
}
|
458 |
-
}
|
459 |
-
|
460 |
-
return true;
|
461 |
-
|
462 |
-
}
|
463 |
-
|
464 |
-
/**
|
465 |
-
* Request the SharedCount data from the API by URL.
|
466 |
-
*
|
467 |
-
* @param string $url The URL to request data for.
|
468 |
-
*
|
469 |
-
* @return bool|mixed
|
470 |
-
*/
|
471 |
-
public function get_counts_by_url( $url ) {
|
472 |
-
|
473 |
-
$url = apply_filters( 'exactmetrics_sharedcount_url_pre_grab', $url );
|
474 |
-
$request_url = add_query_arg(
|
475 |
-
array(
|
476 |
-
'url' => $url,
|
477 |
-
'apikey' => $this->get_api_key(),
|
478 |
-
),
|
479 |
-
$this->get_api_url()
|
480 |
-
);
|
481 |
-
|
482 |
-
$request = wp_remote_get( $request_url );
|
483 |
-
$response = wp_remote_retrieve_body( $request );
|
484 |
-
$parsed_response = json_decode( $response, true );
|
485 |
-
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
|
486 |
-
return $parsed_response;
|
487 |
-
} else {
|
488 |
-
$this->handle_api_error( $parsed_response );
|
489 |
-
|
490 |
-
return false;
|
491 |
-
}
|
492 |
-
|
493 |
-
}
|
494 |
-
|
495 |
-
/**
|
496 |
-
* Schedule a single event for the next page in the WP Query to be grabbed.
|
497 |
-
*
|
498 |
-
* @param int $page The page number.
|
499 |
-
*/
|
500 |
-
public function schedule_next_page( $page ) {
|
501 |
-
|
502 |
-
wp_schedule_single_event( time() + 60, 'exactmetrics_sharedcount_get_more_posts', array( 'page' => $page ) );
|
503 |
-
|
504 |
-
}
|
505 |
-
|
506 |
-
/**
|
507 |
-
* This schedules the daily event with the first one in 24hrs from the current time.
|
508 |
-
*/
|
509 |
-
public function schedule_daily_update() {
|
510 |
-
|
511 |
-
if ( ! wp_next_scheduled( $this->cron_key ) ) {
|
512 |
-
wp_schedule_event( time() + DAY_IN_SECONDS, 'daily', $this->cron_key );
|
513 |
-
}
|
514 |
-
|
515 |
-
}
|
516 |
-
|
517 |
-
/**
|
518 |
-
* Cron handler that checks if the sorting method is still set to SharedCount.
|
519 |
-
* If the sorting method changed, it will disable the daily cron.
|
520 |
-
*/
|
521 |
-
public function daily_cron_update() {
|
522 |
-
$sort_option = exactmetrics_get_option( 'popular_posts_inline_sort', 'comments' );
|
523 |
-
|
524 |
-
if ( 'sharedcount' === $sort_option ) {
|
525 |
-
$this->start_posts_count();
|
526 |
-
} else {
|
527 |
-
$this->disable_counts_updates();
|
528 |
-
}
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Disable cron and reset progress.
|
533 |
-
*/
|
534 |
-
public function disable_counts_updates() {
|
535 |
-
// If we are no longer using this option disable the cron.
|
536 |
-
wp_clear_scheduled_hook( $this->cron_key );
|
537 |
-
$this->reset_progress();
|
538 |
-
}
|
539 |
-
|
540 |
-
/**
|
541 |
-
* Get the post counts based on a post id.
|
542 |
-
* Not used currently.
|
543 |
-
*
|
544 |
-
* @param int $post_id The id of the post.
|
545 |
-
*
|
546 |
-
* @return bool|mixed
|
547 |
-
*/
|
548 |
-
public function get_post_counts( $post_id ) {
|
549 |
-
$post_url = get_permalink( $post_id );
|
550 |
-
|
551 |
-
return $this->combine_counts( $this->get_counts_by_url( $post_url ) );
|
552 |
-
}
|
553 |
-
|
554 |
-
/**
|
555 |
-
* Get the indexing progress as percent.
|
556 |
-
*
|
557 |
-
* @return int
|
558 |
-
*/
|
559 |
-
public static function get_index_progress_percent() {
|
560 |
-
|
561 |
-
$progress = self::get_index_progress();
|
562 |
-
|
563 |
-
if ( ! empty( $progress ) && ! empty( $progress['page'] ) && ! empty( $progress['max_pages'] ) ) {
|
564 |
-
$progress = 100 / $progress['max_pages'] * $progress['page'];
|
565 |
-
$progress = floor( $progress );
|
566 |
-
|
567 |
-
return $progress;
|
568 |
-
} elseif ( isset( $progress['max_pages'] ) && false === $progress['max_pages'] ) {
|
569 |
-
return 100;
|
570 |
-
}
|
571 |
-
|
572 |
-
return 0;
|
573 |
-
|
574 |
-
}
|
575 |
-
|
576 |
-
/**
|
577 |
-
* Get the current progress.
|
578 |
-
*
|
579 |
-
* @return array
|
580 |
-
*/
|
581 |
-
public static function get_index_progress() {
|
582 |
-
|
583 |
-
if ( empty( self::$progress ) ) {
|
584 |
-
self::$progress = get_option( self::$progress_key, array() );
|
585 |
-
}
|
586 |
-
|
587 |
-
return self::$progress;
|
588 |
-
|
589 |
-
}
|
590 |
-
|
591 |
-
/**
|
592 |
-
* Get the index progress with ajax.
|
593 |
-
*/
|
594 |
-
public function ajax_get_index_progress() {
|
595 |
-
wp_send_json( array(
|
596 |
-
'progress' => self::get_index_progress_percent(),
|
597 |
-
) );
|
598 |
-
}
|
599 |
-
|
600 |
-
/**
|
601 |
-
* Get the top popular posts by SharedCount shares.
|
602 |
-
*
|
603 |
-
* @param int $count The number of posts to get.
|
604 |
-
*
|
605 |
-
* @return array
|
606 |
-
*/
|
607 |
-
public static function query_popular_posts( $count = 5 ) {
|
608 |
-
|
609 |
-
$popular_posts_args = array(
|
610 |
-
'posts_per_page' => $count,
|
611 |
-
'meta_value' => 'exactmetrics_sharedcount_total',
|
612 |
-
'orderby' => 'meta_value_num',
|
613 |
-
'order' => 'DESC',
|
614 |
-
);
|
615 |
-
$popular_posts_query = new WP_Query( $popular_posts_args );
|
616 |
-
$popular_posts = array();
|
617 |
-
|
618 |
-
if ( $popular_posts_query->have_posts() ) {
|
619 |
-
while ( $popular_posts_query->have_posts() ) {
|
620 |
-
$popular_posts_query->the_post();
|
621 |
-
$popular_posts[ get_the_ID() ] = array(
|
622 |
-
'post_title' => get_the_title(),
|
623 |
-
'permalink' => get_permalink(),
|
624 |
-
'thumbnail' => get_the_post_thumbnail_url( get_the_ID(), 'medium' ),
|
625 |
-
);
|
626 |
-
}
|
627 |
-
}
|
628 |
-
|
629 |
-
wp_reset_postdata();
|
630 |
-
|
631 |
-
return $popular_posts;
|
632 |
-
|
633 |
-
}
|
634 |
-
|
635 |
-
}
|
636 |
-
|
637 |
-
new ExactMetrics_SharedCount();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Handles the SharedCount integration and count grabbing.
|
5 |
+
*
|
6 |
+
* Class ExactMetrics_SharedCount
|
7 |
+
*/
|
8 |
+
class ExactMetrics_SharedCount {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* The action used to schedule daily events.
|
12 |
+
*
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
public $cron_key = 'exactmetrics_sharedcount_daily_update';
|
16 |
+
/**
|
17 |
+
* Index progress key.
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public static $progress_key = 'exactmetrics_sharedcount_index_progress';
|
22 |
+
/**
|
23 |
+
* Index progress.
|
24 |
+
*
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
public static $progress;
|
28 |
+
/**
|
29 |
+
* The error message from the api call.
|
30 |
+
*
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $error;
|
34 |
+
/**
|
35 |
+
* The API endpoint.
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
private $endpoint = 'https://api.sharedcount.com/v1.0/';
|
40 |
+
/**
|
41 |
+
* The API key to use for the requests.
|
42 |
+
*
|
43 |
+
* @var string
|
44 |
+
*/
|
45 |
+
private $api_key;
|
46 |
+
/**
|
47 |
+
* If the current query needs to run again.
|
48 |
+
*
|
49 |
+
* @var bool
|
50 |
+
*/
|
51 |
+
private $more_pages = false;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* ExactMetrics_SharedCount constructor.
|
55 |
+
*/
|
56 |
+
public function __construct() {
|
57 |
+
|
58 |
+
add_action( 'wp_ajax_exactmetrics_sharedcount_start_indexing', array( $this, 'ajax_start_indexing' ) );
|
59 |
+
add_action( 'wp_ajax_exactmetrics_sharedcount_get_index_progress', array(
|
60 |
+
$this,
|
61 |
+
'ajax_get_index_progress'
|
62 |
+
) );
|
63 |
+
|
64 |
+
add_action( 'exactmetrics_sharedcount_get_more_posts', array( $this, 'get_more_counts' ) );
|
65 |
+
|
66 |
+
add_action( 'exactmetrics_sharedcount_bulk_grab', array( $this, 'grab_and_store_bulk_by_id' ), 10, 2 );
|
67 |
+
|
68 |
+
add_action( $this->cron_key, array( $this, 'daily_cron_update' ) );
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* AJAX handler from the Vue app that checks if the API key is set and handles
|
73 |
+
* an error message from the SharedCount API call. If the first call is successful it will schedule
|
74 |
+
* a daily cron to keep the counts fresh.
|
75 |
+
*/
|
76 |
+
public function ajax_start_indexing() {
|
77 |
+
|
78 |
+
check_ajax_referer( 'mi-admin-nonce', 'nonce' );
|
79 |
+
|
80 |
+
if ( $this->get_api_key() ) {
|
81 |
+
if ( $this->start_posts_count() ) {
|
82 |
+
$this->schedule_daily_update();
|
83 |
+
wp_send_json_success( array(
|
84 |
+
'max_pages' => $this->more_pages,
|
85 |
+
) );
|
86 |
+
} else {
|
87 |
+
wp_send_json_error( array(
|
88 |
+
'message' => $this->error,
|
89 |
+
) );
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
// No API key, let's send an error message.
|
94 |
+
wp_send_json_error( array(
|
95 |
+
'message' => esc_html__( 'The SharedCount API key is not set', 'google-analytics-dashboard-for-wp' ),
|
96 |
+
) );
|
97 |
+
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Get the API key.
|
102 |
+
*
|
103 |
+
* @return string
|
104 |
+
*/
|
105 |
+
public function get_api_key() {
|
106 |
+
|
107 |
+
if ( empty( $this->api_key ) ) {
|
108 |
+
$this->api_key = exactmetrics_get_option( 'sharedcount_key' );
|
109 |
+
}
|
110 |
+
|
111 |
+
return $this->api_key;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Start a grabbing process that will schedule events to grab more pages if needed.
|
116 |
+
*
|
117 |
+
* @return bool
|
118 |
+
*/
|
119 |
+
public function start_posts_count() {
|
120 |
+
|
121 |
+
return $this->get_more_counts( 1 );
|
122 |
+
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Handler for the scheduled event to grab more data for sites with large number of posts.
|
127 |
+
* This is also used by the first call and uses the return value to determine if an error was encountered.
|
128 |
+
* The error gets set in the $error property and used for display.
|
129 |
+
*
|
130 |
+
* @param int $page The page number to grab counts for.
|
131 |
+
*
|
132 |
+
* @return bool
|
133 |
+
*/
|
134 |
+
public function get_more_counts( $page ) {
|
135 |
+
|
136 |
+
$urls = $this->get_post_urls( $page );
|
137 |
+
$urls_as_keys = $this->urls_as_keys( $urls );
|
138 |
+
|
139 |
+
if ( $this->use_bulk_api() ) {
|
140 |
+
$bulk_request = $this->post_bulk_urls( $urls );
|
141 |
+
|
142 |
+
if ( $bulk_request && ! empty( $bulk_request['bulk_id'] ) ) {
|
143 |
+
$this->grab_and_store_bulk_by_id( $bulk_request['bulk_id'], $urls_as_keys );
|
144 |
+
} else {
|
145 |
+
return false;
|
146 |
+
}
|
147 |
+
} else {
|
148 |
+
$store_counts = $this->grab_counts_one_by_one( $urls );
|
149 |
+
if ( ! $store_counts ) {
|
150 |
+
// Error encountered, return error.
|
151 |
+
return false;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
$this->save_progress( $page, $this->more_pages );
|
156 |
+
|
157 |
+
if ( $this->more_pages ) {
|
158 |
+
$page ++;
|
159 |
+
$this->schedule_next_page( $page );
|
160 |
+
}
|
161 |
+
|
162 |
+
return true;
|
163 |
+
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Save the current indexing progress.
|
168 |
+
*
|
169 |
+
* @param int $page The current page.
|
170 |
+
* @param int $max_pages The total number of pages.
|
171 |
+
*/
|
172 |
+
public function save_progress( $page, $max_pages ) {
|
173 |
+
update_option( self::$progress_key, array(
|
174 |
+
'page' => $page,
|
175 |
+
'max_pages' => $max_pages,
|
176 |
+
), false );
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Reset the progress option. Used for when the cron is disabled.
|
181 |
+
*/
|
182 |
+
public function reset_progress() {
|
183 |
+
delete_option( self::$progress_key );
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Use WP_Query to get a list of URLs to query SharedCount for share data.
|
188 |
+
*
|
189 |
+
* @param int $page The page number.
|
190 |
+
*
|
191 |
+
* @return array
|
192 |
+
*/
|
193 |
+
public function get_post_urls( $page = 1 ) {
|
194 |
+
|
195 |
+
$posts_args = array(
|
196 |
+
'posts_per_page' => 100, // Don't try to load more than 500 posts at once.
|
197 |
+
'fields' => 'ids', // Load just the ids.
|
198 |
+
'paged' => $page,
|
199 |
+
'suppress_filters' => true, // Avoid loading additional functionality from other plugins/theme.
|
200 |
+
);
|
201 |
+
$posts_query = new WP_Query( $posts_args );
|
202 |
+
$urls = array();
|
203 |
+
|
204 |
+
if ( $posts_query->have_posts() ) {
|
205 |
+
while ( $posts_query->have_posts() ) {
|
206 |
+
$posts_query->the_post();
|
207 |
+
|
208 |
+
$urls[ get_the_ID() ] = get_permalink( get_the_ID() );
|
209 |
+
}
|
210 |
+
}
|
211 |
+
|
212 |
+
if ( $posts_query->max_num_pages > $page ) {
|
213 |
+
$this->more_pages = $posts_query->max_num_pages;
|
214 |
+
} else {
|
215 |
+
$this->more_pages = false;
|
216 |
+
}
|
217 |
+
|
218 |
+
wp_reset_postdata();
|
219 |
+
|
220 |
+
return $urls;
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Use URLs as array keys to make it easier to match with the post id.
|
225 |
+
*
|
226 |
+
* @param array $urls The urls with post ids as keys.
|
227 |
+
*
|
228 |
+
* @return array
|
229 |
+
*/
|
230 |
+
public function urls_as_keys( $urls ) {
|
231 |
+
|
232 |
+
$urls_as_keys = array();
|
233 |
+
foreach ( $urls as $id => $url ) {
|
234 |
+
$urls_as_keys[ $url ] = $id;
|
235 |
+
}
|
236 |
+
|
237 |
+
return $urls_as_keys;
|
238 |
+
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Helper method for using the bulk API. Disabled by default as the free api doesn't have access to it.
|
243 |
+
* This can be used by large sites to use less requests to the SharedCount API and grab data more efficiently
|
244 |
+
* if they have a paid license.
|
245 |
+
*
|
246 |
+
* @return mixed|void
|
247 |
+
*/
|
248 |
+
public function use_bulk_api() {
|
249 |
+
// Bulk API is not available for free sharedcount accounts so let's set this to off by default.
|
250 |
+
return apply_filters( 'exactmetrics_sharedcount_use_bulk_api', false );
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Use the bulk API method to post data to the SharedCount API.
|
255 |
+
*
|
256 |
+
* @param array $urls An array with the URLs to be sent in the bulk request.
|
257 |
+
*
|
258 |
+
* @return bool|mixed
|
259 |
+
*/
|
260 |
+
public function post_bulk_urls( $urls ) {
|
261 |
+
|
262 |
+
$body = implode( "\n", $urls );
|
263 |
+
|
264 |
+
$request_url = add_query_arg(
|
265 |
+
array(
|
266 |
+
'apikey' => $this->get_api_key(),
|
267 |
+
),
|
268 |
+
$this->get_api_url( 'bulk' )
|
269 |
+
);
|
270 |
+
|
271 |
+
$request = wp_remote_post( $request_url, array(
|
272 |
+
'body' => $body,
|
273 |
+
) );
|
274 |
+
|
275 |
+
$response = wp_remote_retrieve_body( $request );
|
276 |
+
$parsed_response = json_decode( $response, true );
|
277 |
+
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
|
278 |
+
return $parsed_response;
|
279 |
+
} else {
|
280 |
+
$this->handle_api_error( $parsed_response );
|
281 |
+
|
282 |
+
return false;
|
283 |
+
}
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Get the API url.
|
288 |
+
*
|
289 |
+
* @param string $path The API path to use e.g. "bulk".
|
290 |
+
*
|
291 |
+
* @return string
|
292 |
+
*/
|
293 |
+
public function get_api_url( $path = '' ) {
|
294 |
+
// Allow users to override the SharedCount URL if they have a custom URL.
|
295 |
+
return apply_filters( 'exactmetrics_sharedcount_api_url', $this->endpoint . $path );
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Generic handler for error responses from the SharedCount API.
|
300 |
+
* This uses the $error property to pass the error back for being displayed.
|
301 |
+
*
|
302 |
+
* @param array $parsed_response The response object from a SharedCount API call converted to an Array.
|
303 |
+
*/
|
304 |
+
public function handle_api_error( $parsed_response ) {
|
305 |
+
if ( isset( $parsed_response['Error'] ) && isset( $parsed_response['Type'] ) && 'invalid_api_key' === $parsed_response['Type'] ) {
|
306 |
+
$error = esc_html__( 'The SharedCount API key is invalid', 'google-analytics-dashboard-for-wp' );
|
307 |
+
} elseif ( ! empty( $parsed_response['quota_exceeded'] ) ) {
|
308 |
+
$error = $parsed_response['quota_exceeded'];
|
309 |
+
} else {
|
310 |
+
$error = isset( $parsed_response['Error'] ) ? $parsed_response['Error'] : esc_html__( 'There was an error grabbing data from SharedCount, please check the API Key', 'google-analytics-dashboard-for-wp' );
|
311 |
+
}
|
312 |
+
$this->error = $error;
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Attempt to grab bulk data from the API by bulk id, if the bulk request is not completed
|
317 |
+
* schedule an event to try again in a minute.
|
318 |
+
*
|
319 |
+
* @param string $bulk_id The bulk id from the SharedCount bulk post request.
|
320 |
+
* @param array $urls_as_keys An array of URLs where the keys are the URLs and the values are the post ids.
|
321 |
+
*/
|
322 |
+
public function grab_and_store_bulk_by_id( $bulk_id, $urls_as_keys ) {
|
323 |
+
$bulk_data = $this->get_bulk_data( $bulk_id );
|
324 |
+
// If the processing for the current bulk id is not completed schedule a single event to try again.
|
325 |
+
if ( $bulk_data['_meta']['completed'] ) {
|
326 |
+
$this->store_bulk_data( $bulk_data, $urls_as_keys );
|
327 |
+
} else {
|
328 |
+
$this->schedule_bulk_grabbing( $bulk_id, $urls_as_keys );
|
329 |
+
}
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Grab data from the SharedCount API using their Bulk API.
|
334 |
+
*
|
335 |
+
* @param string $bulk_id The bulk id from a POST request to the bulk API.
|
336 |
+
*
|
337 |
+
* @return bool|mixed
|
338 |
+
* @see ExactMetrics_SharedCount::post_bulk_urls()
|
339 |
+
*
|
340 |
+
*/
|
341 |
+
public function get_bulk_data( $bulk_id ) {
|
342 |
+
|
343 |
+
$request_url = add_query_arg(
|
344 |
+
array(
|
345 |
+
'bulk_id' => $bulk_id,
|
346 |
+
'apikey' => $this->get_api_key(),
|
347 |
+
),
|
348 |
+
$this->get_api_url()
|
349 |
+
);
|
350 |
+
|
351 |
+
$request = wp_remote_get( $request_url );
|
352 |
+
|
353 |
+
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
|
354 |
+
$response = wp_remote_retrieve_body( $request );
|
355 |
+
$parsed_response = json_decode( $response, true );
|
356 |
+
|
357 |
+
return $parsed_response;
|
358 |
+
} else {
|
359 |
+
return false;
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Iterate through the bulk data returned and store it in the post meta.
|
365 |
+
*
|
366 |
+
* @param array $bulk_data The bulk data response from the SharedCount API.
|
367 |
+
* @param array $urls_as_keys An array of URLs where the keys are the URLs and the values are the post ids.
|
368 |
+
*/
|
369 |
+
public function store_bulk_data( $bulk_data, $urls_as_keys ) {
|
370 |
+
if ( ! empty( $bulk_data['data'] ) && is_array( $bulk_data['data'] ) ) {
|
371 |
+
foreach ( $bulk_data['data'] as $url => $values ) {
|
372 |
+
$post_id = array_key_exists( $url, $urls_as_keys ) ? $urls_as_keys[ $url ] : false;
|
373 |
+
|
374 |
+
if ( $post_id ) {
|
375 |
+
$this->store_post_counts( $post_id, $values );
|
376 |
+
}
|
377 |
+
}
|
378 |
+
}
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Save the post counts response to the post meta.
|
383 |
+
* The total value is saved separately for querying.
|
384 |
+
*
|
385 |
+
* @param int $post_id The post id to save to.
|
386 |
+
* @param array $values The array of values received from the SharedCount API.
|
387 |
+
*
|
388 |
+
* @see ExactMetrics_SharedCount::get_counts_by_url()
|
389 |
+
*/
|
390 |
+
public function store_post_counts( $post_id, $values ) {
|
391 |
+
$total_count = $this->combine_counts( $values );
|
392 |
+
update_post_meta( $post_id, '_exactmetrics_sharedcount_total', $total_count );
|
393 |
+
update_post_meta( $post_id, '_exactmetrics_sharedcount_values', $values );
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Process a SharedCounts response and compile all counts into one number.
|
398 |
+
*
|
399 |
+
* @param array $response Array from decoding the API JSON response.
|
400 |
+
*
|
401 |
+
* @return int
|
402 |
+
*/
|
403 |
+
public function combine_counts( $response ) {
|
404 |
+
|
405 |
+
$total = 0;
|
406 |
+
if ( ! isset( $response['Error'] ) ) {
|
407 |
+
foreach ( $response as $count ) {
|
408 |
+
if ( is_int( $count ) ) {
|
409 |
+
$total += $count;
|
410 |
+
} elseif ( is_array( $count ) && isset( $count['share_count'] ) ) {
|
411 |
+
$total += $count['share_count'];
|
412 |
+
}
|
413 |
+
}
|
414 |
+
}
|
415 |
+
|
416 |
+
return $total;
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* If the bulk request is not completed we need to schedule it to try again later.
|
421 |
+
*
|
422 |
+
* @param string $bulk_id The bulk id from the SharedCount bulk post request.
|
423 |
+
* @param array $urls_as_keys An array of URLs where the keys are the URLs and the values are the post ids.
|
424 |
+
*
|
425 |
+
* @see ExactMetrics_SharedCount::post_bulk_urls()
|
426 |
+
* @see ExactMetrics_SharedCount::grab_and_store_bulk_by_id()
|
427 |
+
*/
|
428 |
+
public function schedule_bulk_grabbing( $bulk_id, $urls_as_keys ) {
|
429 |
+
|
430 |
+
wp_schedule_single_event( time() + 60, 'exactmetrics_sharedcount_bulk_grab', array(
|
431 |
+
'bulk_id' => $bulk_id,
|
432 |
+
'urls' => $urls_as_keys,
|
433 |
+
) );
|
434 |
+
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* The SharedCount Bulk API is not available for free users so we need
|
439 |
+
* to use multiple calls to the API to grab data.
|
440 |
+
*
|
441 |
+
* @param array $urls An array of urls with the post ids as keys.
|
442 |
+
*
|
443 |
+
* @return bool
|
444 |
+
* @see ExactMetrics_SharedCount::get_post_urls()
|
445 |
+
*
|
446 |
+
*/
|
447 |
+
private function grab_counts_one_by_one( $urls ) {
|
448 |
+
|
449 |
+
foreach ( $urls as $id => $url ) {
|
450 |
+
$counts = $this->get_counts_by_url( $url );
|
451 |
+
|
452 |
+
if ( $counts ) {
|
453 |
+
$this->store_post_counts( $id, $counts );
|
454 |
+
} else {
|
455 |
+
// Return false to display error message from API request.
|
456 |
+
return false;
|
457 |
+
}
|
458 |
+
}
|
459 |
+
|
460 |
+
return true;
|
461 |
+
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* Request the SharedCount data from the API by URL.
|
466 |
+
*
|
467 |
+
* @param string $url The URL to request data for.
|
468 |
+
*
|
469 |
+
* @return bool|mixed
|
470 |
+
*/
|
471 |
+
public function get_counts_by_url( $url ) {
|
472 |
+
|
473 |
+
$url = apply_filters( 'exactmetrics_sharedcount_url_pre_grab', $url );
|
474 |
+
$request_url = add_query_arg(
|
475 |
+
array(
|
476 |
+
'url' => $url,
|
477 |
+
'apikey' => $this->get_api_key(),
|
478 |
+
),
|
479 |
+
$this->get_api_url()
|
480 |
+
);
|
481 |
+
|
482 |
+
$request = wp_remote_get( $request_url );
|
483 |
+
$response = wp_remote_retrieve_body( $request );
|
484 |
+
$parsed_response = json_decode( $response, true );
|
485 |
+
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
|
486 |
+
return $parsed_response;
|
487 |
+
} else {
|
488 |
+
$this->handle_api_error( $parsed_response );
|
489 |
+
|
490 |
+
return false;
|
491 |
+
}
|
492 |
+
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Schedule a single event for the next page in the WP Query to be grabbed.
|
497 |
+
*
|
498 |
+
* @param int $page The page number.
|
499 |
+
*/
|
500 |
+
public function schedule_next_page( $page ) {
|
501 |
+
|
502 |
+
wp_schedule_single_event( time() + 60, 'exactmetrics_sharedcount_get_more_posts', array( 'page' => $page ) );
|
503 |
+
|
504 |
+
}
|
505 |
+
|
506 |
+
/**
|
507 |
+
* This schedules the daily event with the first one in 24hrs from the current time.
|
508 |
+
*/
|
509 |
+
public function schedule_daily_update() {
|
510 |
+
|
511 |
+
if ( ! wp_next_scheduled( $this->cron_key ) ) {
|
512 |
+
wp_schedule_event( time() + DAY_IN_SECONDS, 'daily', $this->cron_key );
|
513 |
+
}
|
514 |
+
|
515 |
+
}
|
516 |
+
|
517 |
+
/**
|
518 |
+
* Cron handler that checks if the sorting method is still set to SharedCount.
|
519 |
+
* If the sorting method changed, it will disable the daily cron.
|
520 |
+
*/
|
521 |
+
public function daily_cron_update() {
|
522 |
+
$sort_option = exactmetrics_get_option( 'popular_posts_inline_sort', 'comments' );
|
523 |
+
|
524 |
+
if ( 'sharedcount' === $sort_option ) {
|
525 |
+
$this->start_posts_count();
|
526 |
+
} else {
|
527 |
+
$this->disable_counts_updates();
|
528 |
+
}
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Disable cron and reset progress.
|
533 |
+
*/
|
534 |
+
public function disable_counts_updates() {
|
535 |
+
// If we are no longer using this option disable the cron.
|
536 |
+
wp_clear_scheduled_hook( $this->cron_key );
|
537 |
+
$this->reset_progress();
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Get the post counts based on a post id.
|
542 |
+
* Not used currently.
|
543 |
+
*
|
544 |
+
* @param int $post_id The id of the post.
|
545 |
+
*
|
546 |
+
* @return bool|mixed
|
547 |
+
*/
|
548 |
+
public function get_post_counts( $post_id ) {
|
549 |
+
$post_url = get_permalink( $post_id );
|
550 |
+
|
551 |
+
return $this->combine_counts( $this->get_counts_by_url( $post_url ) );
|
552 |
+
}
|
553 |
+
|
554 |
+
/**
|
555 |
+
* Get the indexing progress as percent.
|
556 |
+
*
|
557 |
+
* @return int
|
558 |
+
*/
|
559 |
+
public static function get_index_progress_percent() {
|
560 |
+
|
561 |
+
$progress = self::get_index_progress();
|
562 |
+
|
563 |
+
if ( ! empty( $progress ) && ! empty( $progress['page'] ) && ! empty( $progress['max_pages'] ) ) {
|
564 |
+
$progress = 100 / $progress['max_pages'] * $progress['page'];
|
565 |
+
$progress = floor( $progress );
|
566 |
+
|
567 |
+
return $progress;
|
568 |
+
} elseif ( isset( $progress['max_pages'] ) && false === $progress['max_pages'] ) {
|
569 |
+
return 100;
|
570 |
+
}
|
571 |
+
|
572 |
+
return 0;
|
573 |
+
|
574 |
+
}
|
575 |
+
|
576 |
+
/**
|
577 |
+
* Get the current progress.
|
578 |
+
*
|
579 |
+
* @return array
|
580 |
+
*/
|
581 |
+
public static function get_index_progress() {
|
582 |
+
|
583 |
+
if ( empty( self::$progress ) ) {
|
584 |
+
self::$progress = get_option( self::$progress_key, array() );
|
585 |
+
}
|
586 |
+
|
587 |
+
return self::$progress;
|
588 |
+
|
589 |
+
}
|
590 |
+
|
591 |
+
/**
|
592 |
+
* Get the index progress with ajax.
|
593 |
+
*/
|
594 |
+
public function ajax_get_index_progress() {
|
595 |
+
wp_send_json( array(
|
596 |
+
'progress' => self::get_index_progress_percent(),
|
597 |
+
) );
|
598 |
+
}
|
599 |
+
|
600 |
+
/**
|
601 |
+
* Get the top popular posts by SharedCount shares.
|
602 |
+
*
|
603 |
+
* @param int $count The number of posts to get.
|
604 |
+
*
|
605 |
+
* @return array
|
606 |
+
*/
|
607 |
+
public static function query_popular_posts( $count = 5 ) {
|
608 |
+
|
609 |
+
$popular_posts_args = array(
|
610 |
+
'posts_per_page' => $count,
|
611 |
+
'meta_value' => 'exactmetrics_sharedcount_total',
|
612 |
+
'orderby' => 'meta_value_num',
|
613 |
+
'order' => 'DESC',
|
614 |
+
);
|
615 |
+
$popular_posts_query = new WP_Query( $popular_posts_args );
|
616 |
+
$popular_posts = array();
|
617 |
+
|
618 |
+
if ( $popular_posts_query->have_posts() ) {
|
619 |
+
while ( $popular_posts_query->have_posts() ) {
|
620 |
+
$popular_posts_query->the_post();
|
621 |
+
$popular_posts[ get_the_ID() ] = array(
|
622 |
+
'post_title' => get_the_title(),
|
623 |
+
'permalink' => get_permalink(),
|
624 |
+
'thumbnail' => get_the_post_thumbnail_url( get_the_ID(), 'medium' ),
|
625 |
+
);
|
626 |
+
}
|
627 |
+
}
|
628 |
+
|
629 |
+
wp_reset_postdata();
|
630 |
+
|
631 |
+
return $popular_posts;
|
632 |
+
|
633 |
+
}
|
634 |
+
|
635 |
+
}
|
636 |
+
|
637 |
+
new ExactMetrics_SharedCount();
|
includes/admin/uninstall.php
CHANGED
@@ -1,26 +1,26 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Remove various options used in the plugin.
|
5 |
-
*/
|
6 |
-
function exactmetrics_uninstall_remove_options() {
|
7 |
-
|
8 |
-
// Remove usage tracking options.
|
9 |
-
delete_option( 'exactmetrics_usage_tracking_config' );
|
10 |
-
delete_option( 'exactmetrics_usage_tracking_last_checkin' );
|
11 |
-
|
12 |
-
// Remove version options.
|
13 |
-
delete_option( 'exactmetrics_db_version' );
|
14 |
-
delete_option( 'exactmetrics_version_upgraded_from' );
|
15 |
-
|
16 |
-
// Remove other options used for display.
|
17 |
-
delete_option( 'exactmetrics_email_summaries_infoblocks_sent' );
|
18 |
-
delete_option( 'exactmetrics_float_bar_hidden' );
|
19 |
-
delete_option( 'exactmetrics_frontend_tracking_notice_viewed' );
|
20 |
-
delete_option( 'exactmetrics_admin_menu_tooltip' );
|
21 |
-
delete_option( 'exactmetrics_review' );
|
22 |
-
|
23 |
-
// Delete addons transient.
|
24 |
-
delete_transient( 'exactmetrics_addons' );
|
25 |
-
|
26 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Remove various options used in the plugin.
|
5 |
+
*/
|
6 |
+
function exactmetrics_uninstall_remove_options() {
|
7 |
+
|
8 |
+
// Remove usage tracking options.
|
9 |
+
delete_option( 'exactmetrics_usage_tracking_config' );
|
10 |
+
delete_option( 'exactmetrics_usage_tracking_last_checkin' );
|
11 |
+
|
12 |
+
// Remove version options.
|
13 |
+
delete_option( 'exactmetrics_db_version' );
|
14 |
+
delete_option( 'exactmetrics_version_upgraded_from' );
|
15 |
+
|
16 |
+
// Remove other options used for display.
|
17 |
+
delete_option( 'exactmetrics_email_summaries_infoblocks_sent' );
|
18 |
+
delete_option( 'exactmetrics_float_bar_hidden' );
|
19 |
+
delete_option( 'exactmetrics_frontend_tracking_notice_viewed' );
|
20 |
+
delete_option( 'exactmetrics_admin_menu_tooltip' );
|
21 |
+
delete_option( 'exactmetrics_review' );
|
22 |
+
|
23 |
+
// Delete addons transient.
|
24 |
+
delete_transient( 'exactmetrics_addons' );
|
25 |
+
|
26 |
+
}
|
includes/frontend/events/class-gtag-events.php
CHANGED
@@ -1,117 +1,117 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Events JS class.
|
4 |
-
*
|
5 |
-
* @since 6.0.0
|
6 |
-
*
|
7 |
-
* @package ExactMetrics
|
8 |
-
* @subpackage Events
|
9 |
-
* @author Chris Christoff
|
10 |
-
*/
|
11 |
-
|
12 |
-
// Exit if accessed directly
|
13 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
14 |
-
exit;
|
15 |
-
}
|
16 |
-
|
17 |
-
class ExactMetrics_Gtag_Events {
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Holds the name of the events type.
|
21 |
-
*
|
22 |
-
* @since 6.0.0
|
23 |
-
* @access public
|
24 |
-
*
|
25 |
-
* @var string $name Name of the events type.
|
26 |
-
*/
|
27 |
-
public $name = 'js';
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Version of the events class.
|
31 |
-
*
|
32 |
-
* @since 6.0.0
|
33 |
-
* @access public
|
34 |
-
*
|
35 |
-
* @var string $version Version of the events class.
|
36 |
-
*/
|
37 |
-
public $version = '1.0.0';
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Primary class constructor.
|
41 |
-
*
|
42 |
-
* @since 6.0.0
|
43 |
-
* @access public
|
44 |
-
*/
|
45 |
-
public function __construct() {
|
46 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'output_javascript' ), 9 );
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Outputs the Javascript for JS tracking on the page.
|
51 |
-
*
|
52 |
-
* @since 6.0.0
|
53 |
-
* @access public
|
54 |
-
*
|
55 |
-
* @return string
|
56 |
-
*/
|
57 |
-
public function output_javascript() {
|
58 |
-
// Affiliate Links
|
59 |
-
$inbound_paths = exactmetrics_get_option( 'affiliate_links', array() );
|
60 |
-
if ( ! is_array( $inbound_paths ) ) {
|
61 |
-
$inbound_paths = array();
|
62 |
-
} else {
|
63 |
-
foreach( $inbound_paths as $index => $pair ) {
|
64 |
-
// if empty pair, unset and continue
|
65 |
-
if ( empty( $pair['path'] ) ) {
|
66 |
-
unset( $inbound_paths[$index] );
|
67 |
-
continue;
|
68 |
-
}
|
69 |
-
|
70 |
-
// if path does not start with a /, start it with that
|
71 |
-
$path = ! empty( $pair['path'] ) ? $pair['path'] : 'aff';
|
72 |
-
$inbound_paths[$index]['path'] = trim( $path );
|
73 |
-
|
74 |
-
// js escape the link label
|
75 |
-
$label = ! empty( $pair['label'] ) ? $pair['label'] : 'aff';
|
76 |
-
$inbound_paths[$index]['label'] = esc_js( trim( $label ) );
|
77 |
-
}
|
78 |
-
}
|
79 |
-
|
80 |
-
$inbound_paths = wp_json_encode( $inbound_paths );
|
81 |
-
|
82 |
-
// Get download extensions to track
|
83 |
-
$download_extensions = exactmetrics_get_option( 'extensions_of_files', '' );
|
84 |
-
$download_extensions = explode( ',', str_replace( '.', '', $download_extensions ) );
|
85 |
-
if ( ! is_array( $download_extensions ) ) {
|
86 |
-
$download_extensions = array( $download_extensions );
|
87 |
-
}
|
88 |
-
$i = 0;
|
89 |
-
foreach( $download_extensions as $extension ){
|
90 |
-
$download_extensions[ $i ] = esc_js( trim( $extension ) );
|
91 |
-
$i++;
|
92 |
-
}
|
93 |
-
|
94 |
-
$download_extensions = implode( ",", $download_extensions );
|
95 |
-
|
96 |
-
$hash_tracking = exactmetrics_get_option( 'hash_tracking', false ) ? 'true' : 'false';
|
97 |
-
|
98 |
-
$suffix = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
99 |
-
if ( ! file_exists( EXACTMETRICS_PLUGIN_DIR . 'assets/js/frontend-gtag.min.js' ) ) {
|
100 |
-
$suffix = '';
|
101 |
-
}
|
102 |
-
wp_enqueue_script( 'exactmetrics-frontend-script', plugins_url( 'assets/js/frontend-gtag' . $suffix . '.js', EXACTMETRICS_PLUGIN_FILE ), array(), exactmetrics_get_asset_version(), false );
|
103 |
-
wp_localize_script(
|
104 |
-
'exactmetrics-frontend-script',
|
105 |
-
'exactmetrics_frontend',
|
106 |
-
array(
|
107 |
-
'js_events_tracking' => 'true',
|
108 |
-
'download_extensions' => $download_extensions, /* Let's get the extensions to track */
|
109 |
-
'inbound_paths' => $inbound_paths, /* Let's get the internal paths to track */
|
110 |
-
'home_url' => home_url(), /* Let's get the url to compare for external/internal use */
|
111 |
-
'hash_tracking' => $hash_tracking, /* Should hash track */
|
112 |
-
'ua' => exactmetrics_get_ua(), /* UA code used for tracking */
|
113 |
-
'v4_id' => exactmetrics_get_v4_id(), /* V4 ID used for tracking */
|
114 |
-
)
|
115 |
-
);
|
116 |
-
}
|
117 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Events JS class.
|
4 |
+
*
|
5 |
+
* @since 6.0.0
|
6 |
+
*
|
7 |
+
* @package ExactMetrics
|
8 |
+
* @subpackage Events
|
9 |
+
* @author Chris Christoff
|
10 |
+
*/
|
11 |
+
|
12 |
+
// Exit if accessed directly
|
13 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
14 |
+
exit;
|
15 |
+
}
|
16 |
+
|
17 |
+
class ExactMetrics_Gtag_Events {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Holds the name of the events type.
|
21 |
+
*
|
22 |
+
* @since 6.0.0
|
23 |
+
* @access public
|
24 |
+
*
|
25 |
+
* @var string $name Name of the events type.
|
26 |
+
*/
|
27 |
+
public $name = 'js';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Version of the events class.
|
31 |
+
*
|
32 |
+
* @since 6.0.0
|
33 |
+
* @access public
|
34 |
+
*
|
35 |
+
* @var string $version Version of the events class.
|
36 |
+
*/
|
37 |
+
public $version = '1.0.0';
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Primary class constructor.
|
41 |
+
*
|
42 |
+
* @since 6.0.0
|
43 |
+
* @access public
|
44 |
+
*/
|
45 |
+
public function __construct() {
|
46 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'output_javascript' ), 9 );
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Outputs the Javascript for JS tracking on the page.
|
51 |
+
*
|
52 |
+
* @since 6.0.0
|
53 |
+
* @access public
|
54 |
+
*
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
public function output_javascript() {
|
58 |
+
// Affiliate Links
|
59 |
+
$inbound_paths = exactmetrics_get_option( 'affiliate_links', array() );
|
60 |
+
if ( ! is_array( $inbound_paths ) ) {
|
61 |
+
$inbound_paths = array();
|
62 |
+
} else {
|
63 |
+
foreach( $inbound_paths as $index => $pair ) {
|
64 |
+
// if empty pair, unset and continue
|
65 |
+
if ( empty( $pair['path'] ) ) {
|
66 |
+
unset( $inbound_paths[$index] );
|
67 |
+
continue;
|
68 |
+
}
|
69 |
+
|
70 |
+
// if path does not start with a /, start it with that
|
71 |
+
$path = ! empty( $pair['path'] ) ? $pair['path'] : 'aff';
|
72 |
+
$inbound_paths[$index]['path'] = trim( $path );
|
73 |
+
|
74 |
+
// js escape the link label
|
75 |
+
$label = ! empty( $pair['label'] ) ? $pair['label'] : 'aff';
|
76 |
+
$inbound_paths[$index]['label'] = esc_js( trim( $label ) );
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
$inbound_paths = wp_json_encode( $inbound_paths );
|
81 |
+
|
82 |
+
// Get download extensions to track
|
83 |
+
$download_extensions = exactmetrics_get_option( 'extensions_of_files', '' );
|
84 |
+
$download_extensions = explode( ',', str_replace( '.', '', $download_extensions ) );
|
85 |
+
if ( ! is_array( $download_extensions ) ) {
|
86 |
+
$download_extensions = array( $download_extensions );
|
87 |
+
}
|
88 |
+
$i = 0;
|
89 |
+
foreach( $download_extensions as $extension ){
|
90 |
+
$download_extensions[ $i ] = esc_js( trim( $extension ) );
|
91 |
+
$i++;
|
92 |
+
}
|
93 |
+
|
94 |
+
$download_extensions = implode( ",", $download_extensions );
|
95 |
+
|
96 |
+
$hash_tracking = exactmetrics_get_option( 'hash_tracking', false ) ? 'true' : 'false';
|
97 |
+
|
98 |
+
$suffix = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
99 |
+
if ( ! file_exists( EXACTMETRICS_PLUGIN_DIR . 'assets/js/frontend-gtag.min.js' ) ) {
|
100 |
+
$suffix = '';
|
101 |
+
}
|
102 |
+
wp_enqueue_script( 'exactmetrics-frontend-script', plugins_url( 'assets/js/frontend-gtag' . $suffix . '.js', EXACTMETRICS_PLUGIN_FILE ), array(), exactmetrics_get_asset_version(), false );
|
103 |
+
wp_localize_script(
|
104 |
+
'exactmetrics-frontend-script',
|
105 |
+
'exactmetrics_frontend',
|
106 |
+
array(
|
107 |
+
'js_events_tracking' => 'true',
|
108 |
+
'download_extensions' => $download_extensions, /* Let's get the extensions to track */
|
109 |
+
'inbound_paths' => $inbound_paths, /* Let's get the internal paths to track */
|
110 |
+
'home_url' => home_url(), /* Let's get the url to compare for external/internal use */
|
111 |
+
'hash_tracking' => $hash_tracking, /* Should hash track */
|
112 |
+
'ua' => exactmetrics_get_ua(), /* UA code used for tracking */
|
113 |
+
'v4_id' => exactmetrics_get_v4_id(), /* V4 ID used for tracking */
|
114 |
+
)
|
115 |
+
);
|
116 |
+
}
|
117 |
+
}
|
includes/frontend/tracking/class-tracking-gtag.php
CHANGED
@@ -1,486 +1,486 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Tracking gtag.js class.
|
4 |
-
*
|
5 |
-
* @since 7.15.0
|
6 |
-
*
|
7 |
-
* @package ExactMetrics
|
8 |
-
* @author Mircea Sandu
|
9 |
-
*/
|
10 |
-
|
11 |
-
// Exit if accessed directly
|
12 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
13 |
-
exit;
|
14 |
-
}
|
15 |
-
|
16 |
-
class ExactMetrics_Tracking_Gtag extends ExactMetrics_Tracking_Abstract {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Holds the name of the tracking type.
|
20 |
-
*
|
21 |
-
* @since 7.15.0
|
22 |
-
* @access public
|
23 |
-
*
|
24 |
-
* @var string $name Name of the tracking type.
|
25 |
-
*/
|
26 |
-
public $name = 'gtag';
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Version of the tracking class.
|
30 |
-
*
|
31 |
-
* @since 7.15.0
|
32 |
-
* @access public
|
33 |
-
*
|
34 |
-
* @var string $version Version of the tracking class.
|
35 |
-
*/
|
36 |
-
public $version = '1.0.0';
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Primary class constructor.
|
40 |
-
*
|
41 |
-
* @since 7.15.0
|
42 |
-
* @access public
|
43 |
-
*/
|
44 |
-
public function __construct() {
|
45 |
-
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Array of options that will be made persistent by setting them before the pageview.
|
50 |
-
*
|
51 |
-
* @see https://developers.google.com/analytics/devguides/collection/gtagjs/setting-values
|
52 |
-
* @return array Options for persistent values, like custom dimensions.
|
53 |
-
* @since 7.15.0
|
54 |
-
* @access public
|
55 |
-
*/
|
56 |
-
public function frontend_tracking_options_persistent() {
|
57 |
-
$options = apply_filters( 'exactmetrics_frontend_tracking_options_persistent_gtag_before_pageview', array() );
|
58 |
-
|
59 |
-
return $options;
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Get frontend tracking options for the gtag script.
|
64 |
-
*
|
65 |
-
* This function is used to return an array of parameters
|
66 |
-
* for the frontend_output() function to output. These are
|
67 |
-
* generally dimensions and turned on GA features.
|
68 |
-
*
|
69 |
-
* @param bool $encoded Whether to return a JavaScript object representation of the options
|
70 |
-
*
|
71 |
-
* @return array|string Options for the gtag config.
|
72 |
-
* @since 7.15.0
|
73 |
-
* @access public
|
74 |
-
*
|
75 |
-
*/
|
76 |
-
public function frontend_tracking_options( $type = 'ua', $encoded = false ) {
|
77 |
-
global $wp_query;
|
78 |
-
$options = array();
|
79 |
-
|
80 |
-
$tracking_ids = exactmetrics_get_tracking_ids();
|
81 |
-
if ( empty( $tracking_ids ) ) {
|
82 |
-
return $encoded ? wp_json_encode( $options ) : $options;
|
83 |
-
}
|
84 |
-
|
85 |
-
$placeholder = '';
|
86 |
-
|
87 |
-
if ( $encoded ) {
|
88 |
-
$placeholder = '!@#';
|
89 |
-
}
|
90 |
-
|
91 |
-
// $track_user = exactmetrics_track_user();
|
92 |
-
//
|
93 |
-
// if ( ! $track_user ) {
|
94 |
-
// $options['create'] = "'create', '" . esc_js( $ua_code ) . "', '" . esc_js( 'auto' ) . "'";
|
95 |
-
// $options['forceSSL'] = "'set', 'forceSSL', true";
|
96 |
-
// $options['send'] = "'send','pageview'";
|
97 |
-
//
|
98 |
-
// return $options;
|
99 |
-
// }
|
100 |
-
|
101 |
-
$cross_domains = exactmetrics_get_option( 'cross_domains', array() );
|
102 |
-
$allow_anchor = exactmetrics_get_option( 'allow_anchor', false );
|
103 |
-
|
104 |
-
if ( $allow_anchor ) {
|
105 |
-
$options['allow_anchor'] = 'true';
|
106 |
-
}
|
107 |
-
|
108 |
-
if ( class_exists( 'ExactMetrics_AMP' ) ) {
|
109 |
-
$options['use_amp_client_id'] = 'true';
|
110 |
-
}
|
111 |
-
|
112 |
-
|
113 |
-
$options['forceSSL'] = 'true';
|
114 |
-
|
115 |
-
// Anonymous data.
|
116 |
-
if ( exactmetrics_get_option( 'anonymize_ips', false ) ) {
|
117 |
-
$options['anonymize_ip'] = 'true';
|
118 |
-
}
|
119 |
-
|
120 |
-
$options = apply_filters( 'exactmetrics_frontend_tracking_options_gtag_before_scripts', $options );
|
121 |
-
|
122 |
-
// Add Enhanced link attribution.
|
123 |
-
if ( exactmetrics_get_option( 'link_attribution', false ) ) {
|
124 |
-
$options['link_attribution'] = 'true';
|
125 |
-
}
|
126 |
-
|
127 |
-
// Add cross-domain tracking.
|
128 |
-
if ( is_array( $cross_domains ) && ! empty( $cross_domains ) ) {
|
129 |
-
$linker_domains = array();
|
130 |
-
foreach ( $cross_domains as $cross_domain ) {
|
131 |
-
if ( ! empty( $cross_domain['domain'] ) ) {
|
132 |
-
$linker_domains[] = $cross_domain['domain'];
|
133 |
-
}
|
134 |
-
}
|
135 |
-
$options['linker'] = array(
|
136 |
-
'domains' => $linker_domains,
|
137 |
-
);
|
138 |
-
}
|
139 |
-
|
140 |
-
if ( exactmetrics_is_debug_mode() ) {
|
141 |
-
$options['debug_mode'] = true;
|
142 |
-
}
|
143 |
-
|
144 |
-
$options = apply_filters( 'exactmetrics_frontend_tracking_options_gtag_before_pageview', $options, $type );
|
145 |
-
$options = apply_filters( 'exactmetrics_frontend_tracking_options_before_pageview', $options, $this->name, $this->version, $type );
|
146 |
-
|
147 |
-
if ( is_404() ) {
|
148 |
-
if ( exactmetrics_get_option( 'hash_tracking', false ) ) {
|
149 |
-
$options['page_path'] = "${placeholder}'/404.html?page=' + document.location.pathname + document.location.search + location.hash + '&from=' + document.referrer${placeholder}";
|
150 |
-
} else {
|
151 |
-
$options['page_path'] = "${placeholder}'/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer${placeholder}";
|
152 |
-
}
|
153 |
-
} else if ( $wp_query->is_search ) {
|
154 |
-
$pushstr = "'/?s=";
|
155 |
-
if ( 0 === (int) $wp_query->found_posts ) {
|
156 |
-
$options['page_path'] = $pushstr . 'no-results:' . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
|
157 |
-
} else if ( (int) $wp_query->found_posts === 1 ) {
|
158 |
-
$options['page_path'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
|
159 |
-
} else if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
|
160 |
-
$options['page_path'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
|
161 |
-
} else {
|
162 |
-
$options['page_path'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
|
163 |
-
}
|
164 |
-
} else if ( exactmetrics_get_option( 'hash_tracking', false ) ) {
|
165 |
-
$options['page_path'] = "${placeholder}location.pathname + location.search + location.hash${placeholder}";
|
166 |
-
}
|
167 |
-
|
168 |
-
$options = apply_filters( 'exactmetrics_frontend_tracking_options_gtag_end', $options, $type );
|
169 |
-
|
170 |
-
if ( $encoded ) {
|
171 |
-
return str_replace(
|
172 |
-
array( '"' . $placeholder, $placeholder . '"' ),
|
173 |
-
'',
|
174 |
-
wp_json_encode( $options )
|
175 |
-
);
|
176 |
-
}
|
177 |
-
|
178 |
-
return $options;
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Get frontend output.
|
183 |
-
*
|
184 |
-
* This function is used to return the Javascript
|
185 |
-
* to output in the head of the page for the given
|
186 |
-
* tracking method.
|
187 |
-
*
|
188 |
-
* @return string Javascript to output.
|
189 |
-
* @since 7.15.0
|
190 |
-
* @access public
|
191 |
-
*
|
192 |
-
*/
|
193 |
-
public function frontend_output() {
|
194 |
-
$options = $this->frontend_tracking_options( 'ua', true );
|
195 |
-
$options_v4 = $this->frontend_tracking_options( 'v4', true );
|
196 |
-
$persistent = $this->frontend_tracking_options_persistent();
|
197 |
-
$connected_type = ExactMetrics()->auth->get_connected_type();
|
198 |
-
$v4_id = exactmetrics_get_v4_id_to_output();
|
199 |
-
$ua = exactmetrics_get_ua_to_output();
|
200 |
-
$main_id = $connected_type === 'ua' ? $ua : $v4_id;
|
201 |
-
$src = apply_filters( 'exactmetrics_frontend_output_gtag_src', '//www.googletagmanager.com/gtag/js?id=' . $main_id );
|
202 |
-
$compat_mode = apply_filters( 'exactmetrics_get_option_gtagtracker_compatibility_mode', true );
|
203 |
-
$compat = $compat_mode ? 'window.gtag = __gtagTracker;' : '';
|
204 |
-
$track_user = exactmetrics_track_user();
|
205 |
-
$output = '';
|
206 |
-
$reason = '';
|
207 |
-
$attr_string = exactmetrics_get_frontend_analytics_script_atts();
|
208 |
-
$gtag_async = apply_filters( 'exactmetrics_frontend_gtag_script_async', true ) ? 'async' : '';
|
209 |
-
ob_start();
|
210 |
-
?>
|
211 |
-
<!-- This site uses the Google Analytics by ExactMetrics plugin v<?php echo EXACTMETRICS_VERSION; ?> - Using Analytics tracking - https://www.exactmetrics.com/ -->
|
212 |
-
<?php if ( ! $track_user ) {
|
213 |
-
if ( empty( $v4_id ) && empty( $ua ) ) {
|
214 |
-
$reason = __( 'Note: ExactMetrics is not currently configured on this site. The site owner needs to authenticate with Google Analytics in the ExactMetrics settings panel.', 'google-analytics-dashboard-for-wp' );
|
215 |
-
$output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
|
216 |
-
} else if ( current_user_can( 'exactmetrics_save_settings' ) ) {
|
217 |
-
$reason = __( 'Note: ExactMetrics does not track you as a logged-in site administrator to prevent site owners from accidentally skewing their own Google Analytics data.' . PHP_EOL . 'If you are testing Google Analytics code, please do so either logged out or in the private browsing/incognito mode of your web browser.', 'google-analytics-dashboard-for-wp' );
|
218 |
-
$output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
|
219 |
-
} else {
|
220 |
-
$reason = __( 'Note: The site owner has disabled Google Analytics tracking for your user role.', 'google-analytics-dashboard-for-wp' );
|
221 |
-
$output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
|
222 |
-
}
|
223 |
-
echo $output;
|
224 |
-
} ?>
|
225 |
-
<?php if ( ! empty( $v4_id ) || ! empty( $ua ) ) { ?>
|
226 |
-
<script src="<?php echo esc_attr( $src ); ?>" <?php echo $attr_string; ?> <?php echo esc_attr( $gtag_async ); ?>></script>
|
227 |
-
<script<?php echo $attr_string; ?>>
|
228 |
-
var em_version = '<?php echo EXACTMETRICS_VERSION; ?>';
|
229 |
-
var em_track_user = <?php echo( $track_user ? 'true' : 'false' ); ?>;
|
230 |
-
var em_no_track_reason = <?php echo( $reason ? "'" . esc_js( $reason ) . "'" : "''" ); ?>;
|
231 |
-
<?php do_action( 'exactmetrics_tracking_gtag_frontend_output_after_em_track_user' ); ?>
|
232 |
-
|
233 |
-
<?php if ( $this->should_do_optout() ) { ?>
|
234 |
-
var disableStrs = [
|
235 |
-
<?php if ( ! empty( $v4_id ) ): ?>
|
236 |
-
'ga-disable-<?php echo esc_js( $v4_id ); ?>',
|
237 |
-
<?php endif; ?>
|
238 |
-
<?php if ( ! empty( $ua ) ): ?>
|
239 |
-
'ga-disable-<?php echo esc_js( $ua ); ?>',
|
240 |
-
<?php endif; ?>
|
241 |
-
];
|
242 |
-
|
243 |
-
/* Function to detect opted out users */
|
244 |
-
function __gtagTrackerIsOptedOut() {
|
245 |
-
for ( var index = 0; index < disableStrs.length; index++ ) {
|
246 |
-
if ( document.cookie.indexOf( disableStrs[ index ] + '=true' ) > -1 ) {
|
247 |
-
return true;
|
248 |
-
}
|
249 |
-
}
|
250 |
-
|
251 |
-
return false;
|
252 |
-
}
|
253 |
-
|
254 |
-
/* Disable tracking if the opt-out cookie exists. */
|
255 |
-
if ( __gtagTrackerIsOptedOut() ) {
|
256 |
-
for ( var index = 0; index < disableStrs.length; index++ ) {
|
257 |
-
window[ disableStrs[ index ] ] = true;
|
258 |
-
}
|
259 |
-
}
|
260 |
-
|
261 |
-
/* Opt-out function */
|
262 |
-
function __gtagTrackerOptout() {
|
263 |
-
for ( var index = 0; index < disableStrs.length; index++ ) {
|
264 |
-
document.cookie = disableStrs[ index ] + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';
|
265 |
-
window[ disableStrs[ index ] ] = true;
|
266 |
-
}
|
267 |
-
}
|
268 |
-
|
269 |
-
if ( 'undefined' === typeof gaOptout ) {
|
270 |
-
function gaOptout() {
|
271 |
-
__gtagTrackerOptout();
|
272 |
-
}
|
273 |
-
}
|
274 |
-
<?php } ?>
|
275 |
-
window.dataLayer = window.dataLayer || [];
|
276 |
-
|
277 |
-
window.ExactMetricsDualTracker = {
|
278 |
-
helpers: {},
|
279 |
-
trackers: {},
|
280 |
-
};
|
281 |
-
if ( em_track_user ) {
|
282 |
-
function __gtagDataLayer() {
|
283 |
-
dataLayer.push( arguments );
|
284 |
-
}
|
285 |
-
|
286 |
-
function __gtagTracker( type, name, parameters ) {
|
287 |
-
if (!parameters) {
|
288 |
-
parameters = {};
|
289 |
-
}
|
290 |
-
|
291 |
-
if (parameters.send_to) {
|
292 |
-
__gtagDataLayer.apply( null, arguments );
|
293 |
-
return;
|
294 |
-
}
|
295 |
-
|
296 |
-
if ( type === 'event' ) {
|
297 |
-
<?php if ( $v4_id ): ?>
|
298 |
-
parameters.send_to = exactmetrics_frontend.v4_id;
|
299 |
-
var hookName = name;
|
300 |
-
if ( typeof parameters[ 'event_category' ] !== 'undefined' ) {
|
301 |
-
hookName = parameters[ 'event_category' ] + ':' + name;
|
302 |
-
}
|
303 |
-
|
304 |
-
if ( typeof ExactMetricsDualTracker.trackers[ hookName ] !== 'undefined' ) {
|
305 |
-
ExactMetricsDualTracker.trackers[ hookName ]( parameters );
|
306 |
-
} else {
|
307 |
-
__gtagDataLayer( 'event', name, parameters );
|
308 |
-
}
|
309 |
-
<?php endif; ?>
|
310 |
-
|
311 |
-
<?php if ( $ua ): ?>
|
312 |
-
parameters.send_to = exactmetrics_frontend.ua;
|
313 |
-
__gtagDataLayer( type, name, parameters );
|
314 |
-
<?php endif; ?>
|
315 |
-
} else {
|
316 |
-
__gtagDataLayer.apply( null, arguments );
|
317 |
-
}
|
318 |
-
}
|
319 |
-
__gtagTracker( 'js', new Date() );
|
320 |
-
__gtagTracker( 'set', {
|
321 |
-
'developer_id.dNDMyYj' : true,
|
322 |
-
<?php
|
323 |
-
if ( ! empty( $persistent ) ) {
|
324 |
-
foreach ( $persistent as $key => $value ) {
|
325 |
-
echo "'" . esc_js( $key ) . "' : '" . esc_js( $value ) . "',";
|
326 |
-
}
|
327 |
-
}
|
328 |
-
?>
|
329 |
-
} );
|
330 |
-
<?php if ( ! empty( $v4_id ) ): ?>
|
331 |
-
__gtagTracker( 'config', '<?php echo esc_js( $v4_id ); ?>', <?php echo $options_v4; ?> );
|
332 |
-
<?php endif; ?>
|
333 |
-
<?php if ( ! empty( $ua ) ): ?>
|
334 |
-
__gtagTracker( 'config', '<?php echo esc_js( $ua ); ?>', <?php echo $options; ?> );
|
335 |
-
<?php
|
336 |
-
endif;
|
337 |
-
/**
|
338 |
-
* Extend or enhance the functionality by adding custom code to frontend
|
339 |
-
* tracking via this hook.
|
340 |
-
*
|
341 |
-
* @since 7.15.0
|
342 |
-
*/
|
343 |
-
do_action( 'exactmetrics_frontend_tracking_gtag_after_pageview' );
|
344 |
-
?>
|
345 |
-
<?php echo esc_js( $compat ); ?>
|
346 |
-
<?php if ( apply_filters( 'exactmetrics_tracking_gtag_frontend_gatracker_compatibility', true ) ) { ?>
|
347 |
-
(
|
348 |
-
function () {
|
349 |
-
/* https://developers.google.com/analytics/devguides/collection/analyticsjs/ */
|
350 |
-
/* ga and __gaTracker compatibility shim. */
|
351 |
-
var noopfn = function () {
|
352 |
-
return null;
|
353 |
-
};
|
354 |
-
var newtracker = function () {
|
355 |
-
return new Tracker();
|
356 |
-
};
|
357 |
-
var Tracker = function () {
|
358 |
-
return null;
|
359 |
-
};
|
360 |
-
var p = Tracker.prototype;
|
361 |
-
p.get = noopfn;
|
362 |
-
p.set = noopfn;
|
363 |
-
p.send = function (){
|
364 |
-
var args = Array.prototype.slice.call(arguments);
|
365 |
-
args.unshift( 'send' );
|
366 |
-
__gaTracker.apply(null, args);
|
367 |
-
};
|
368 |
-
var __gaTracker = function () {
|
369 |
-
var len = arguments.length;
|
370 |
-
if ( len === 0 ) {
|
371 |
-
return;
|
372 |
-
}
|
373 |
-
var f = arguments[len - 1];
|
374 |
-
if ( typeof f !== 'object' || f === null || typeof f.hitCallback !== 'function' ) {
|
375 |
-
if ( 'send' === arguments[0] ) {
|
376 |
-
var hitConverted, hitObject = false, action;
|
377 |
-
if ( 'event' === arguments[1] ) {
|
378 |
-
if ( 'undefined' !== typeof arguments[3] ) {
|
379 |
-
hitObject = {
|
380 |
-
'eventAction': arguments[3],
|
381 |
-
'eventCategory': arguments[2],
|
382 |
-
'eventLabel': arguments[4],
|
383 |
-
'value': arguments[5] ? arguments[5] : 1,
|
384 |
-
}
|
385 |
-
}
|
386 |
-
}
|
387 |
-
if ( 'pageview' === arguments[1] ) {
|
388 |
-
if ( 'undefined' !== typeof arguments[2] ) {
|
389 |
-
hitObject = {
|
390 |
-
'eventAction': 'page_view',
|
391 |
-
'page_path' : arguments[2],
|
392 |
-
}
|
393 |
-
}
|
394 |
-
}
|
395 |
-
if ( typeof arguments[2] === 'object' ) {
|
396 |
-
hitObject = arguments[2];
|
397 |
-
}
|
398 |
-
if ( typeof arguments[5] === 'object' ) {
|
399 |
-
Object.assign( hitObject, arguments[5] );
|
400 |
-
}
|
401 |
-
if ( 'undefined' !== typeof arguments[1].hitType ) {
|
402 |
-
hitObject = arguments[1];
|
403 |
-
if ( 'pageview' === hitObject.hitType ) {
|
404 |
-
hitObject.eventAction = 'page_view';
|
405 |
-
}
|
406 |
-
}
|
407 |
-
if ( hitObject ) {
|
408 |
-
action = 'timing' === arguments[1].hitType ? 'timing_complete' : hitObject.eventAction;
|
409 |
-
hitConverted = mapArgs( hitObject );
|
410 |
-
__gtagTracker( 'event', action, hitConverted );
|
411 |
-
}
|
412 |
-
}
|
413 |
-
return;
|
414 |
-
}
|
415 |
-
|
416 |
-
function mapArgs( args ) {
|
417 |
-
var arg, hit = {};
|
418 |
-
var gaMap = {
|
419 |
-
'eventCategory': 'event_category',
|
420 |
-
'eventAction': 'event_action',
|
421 |
-
'eventLabel': 'event_label',
|
422 |
-
'eventValue': 'event_value',
|
423 |
-
'nonInteraction': 'non_interaction',
|
424 |
-
'timingCategory': 'event_category',
|
425 |
-
'timingVar': 'name',
|
426 |
-
'timingValue': 'value',
|
427 |
-
'timingLabel': 'event_label',
|
428 |
-
'page' : 'page_path',
|
429 |
-
'location' : 'page_location',
|
430 |
-
'title' : 'page_title',
|
431 |
-
};
|
432 |
-
for ( arg in args ) {
|
433 |
-
<?php // Note: we do || instead of && because FBIA can't encode && properly. ?>
|
434 |
-
if ( ! ( ! args.hasOwnProperty(arg) || ! gaMap.hasOwnProperty(arg) ) ) {
|
435 |
-
hit[gaMap[arg]] = args[arg];
|
436 |
-
} else {
|
437 |
-
hit[arg] = args[arg];
|
438 |
-
}
|
439 |
-
}
|
440 |
-
return hit;
|
441 |
-
}
|
442 |
-
|
443 |
-
try {
|
444 |
-
f.hitCallback();
|
445 |
-
} catch ( ex ) {
|
446 |
-
}
|
447 |
-
};
|
448 |
-
__gaTracker.create = newtracker;
|
449 |
-
__gaTracker.getByName = newtracker;
|
450 |
-
__gaTracker.getAll = function () {
|
451 |
-
return [];
|
452 |
-
};
|
453 |
-
__gaTracker.remove = noopfn;
|
454 |
-
__gaTracker.loaded = true;
|
455 |
-
window['__gaTracker'] = __gaTracker;
|
456 |
-
}
|
457 |
-
)();
|
458 |
-
<?php } ?>
|
459 |
-
} else {
|
460 |
-
<?php if ( $this->should_do_optout() ) { ?>
|
461 |
-
console.log( "<?php echo esc_js( $reason );?>" );
|
462 |
-
( function () {
|
463 |
-
function __gtagTracker() {
|
464 |
-
return null;
|
465 |
-
}
|
466 |
-
window['__gtagTracker'] = __gtagTracker;
|
467 |
-
window['gtag'] = __gtagTracker;
|
468 |
-
} )();
|
469 |
-
<?php } ?>
|
470 |
-
}
|
471 |
-
</script>
|
472 |
-
<?php } else { ?>
|
473 |
-
<!-- No UA code set -->
|
474 |
-
<?php } ?>
|
475 |
-
<!-- / Google Analytics by ExactMetrics -->
|
476 |
-
<?php
|
477 |
-
$output = ob_get_contents();
|
478 |
-
ob_end_clean();
|
479 |
-
|
480 |
-
return $output;
|
481 |
-
}
|
482 |
-
|
483 |
-
public function should_do_optout() {
|
484 |
-
return ! ( defined( 'EM_NO_TRACKING_OPTOUT' ) && EM_NO_TRACKING_OPTOUT );
|
485 |
-
}
|
486 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Tracking gtag.js class.
|
4 |
+
*
|
5 |
+
* @since 7.15.0
|
6 |
+
*
|
7 |
+
* @package ExactMetrics
|
8 |
+
* @author Mircea Sandu
|
9 |
+
*/
|
10 |
+
|
11 |
+
// Exit if accessed directly
|
12 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
13 |
+
exit;
|
14 |
+
}
|
15 |
+
|
16 |
+
class ExactMetrics_Tracking_Gtag extends ExactMetrics_Tracking_Abstract {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Holds the name of the tracking type.
|
20 |
+
*
|
21 |
+
* @since 7.15.0
|
22 |
+
* @access public
|
23 |
+
*
|
24 |
+
* @var string $name Name of the tracking type.
|
25 |
+
*/
|
26 |
+
public $name = 'gtag';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Version of the tracking class.
|
30 |
+
*
|
31 |
+
* @since 7.15.0
|
32 |
+
* @access public
|
33 |
+
*
|
34 |
+
* @var string $version Version of the tracking class.
|
35 |
+
*/
|
36 |
+
public $version = '1.0.0';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Primary class constructor.
|
40 |
+
*
|
41 |
+
* @since 7.15.0
|
42 |
+
* @access public
|
43 |
+
*/
|
44 |
+
public function __construct() {
|
45 |
+
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Array of options that will be made persistent by setting them before the pageview.
|
50 |
+
*
|
51 |
+
* @see https://developers.google.com/analytics/devguides/collection/gtagjs/setting-values
|
52 |
+
* @return array Options for persistent values, like custom dimensions.
|
53 |
+
* @since 7.15.0
|
54 |
+
* @access public
|
55 |
+
*/
|
56 |
+
public function frontend_tracking_options_persistent() {
|
57 |
+
$options = apply_filters( 'exactmetrics_frontend_tracking_options_persistent_gtag_before_pageview', array() );
|
58 |
+
|
59 |
+
return $options;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get frontend tracking options for the gtag script.
|
64 |
+
*
|
65 |
+
* This function is used to return an array of parameters
|
66 |
+
* for the frontend_output() function to output. These are
|
67 |
+
* generally dimensions and turned on GA features.
|
68 |
+
*
|
69 |
+
* @param bool $encoded Whether to return a JavaScript object representation of the options
|
70 |
+
*
|
71 |
+
* @return array|string Options for the gtag config.
|
72 |
+
* @since 7.15.0
|
73 |
+
* @access public
|
74 |
+
*
|
75 |
+
*/
|
76 |
+
public function frontend_tracking_options( $type = 'ua', $encoded = false ) {
|
77 |
+
global $wp_query;
|
78 |
+
$options = array();
|
79 |
+
|
80 |
+
$tracking_ids = exactmetrics_get_tracking_ids();
|
81 |
+
if ( empty( $tracking_ids ) ) {
|
82 |
+
return $encoded ? wp_json_encode( $options ) : $options;
|
83 |
+
}
|
84 |
+
|
85 |
+
$placeholder = '';
|
86 |
+
|
87 |
+
if ( $encoded ) {
|
88 |
+
$placeholder = '!@#';
|
89 |
+
}
|
90 |
+
|
91 |
+
// $track_user = exactmetrics_track_user();
|
92 |
+
//
|
93 |
+
// if ( ! $track_user ) {
|
94 |
+
// $options['create'] = "'create', '" . esc_js( $ua_code ) . "', '" . esc_js( 'auto' ) . "'";
|
95 |
+
// $options['forceSSL'] = "'set', 'forceSSL', true";
|
96 |
+
// $options['send'] = "'send','pageview'";
|
97 |
+
//
|
98 |
+
// return $options;
|
99 |
+
// }
|
100 |
+
|
101 |
+
$cross_domains = exactmetrics_get_option( 'cross_domains', array() );
|
102 |
+
$allow_anchor = exactmetrics_get_option( 'allow_anchor', false );
|
103 |
+
|
104 |
+
if ( $allow_anchor ) {
|
105 |
+
$options['allow_anchor'] = 'true';
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( class_exists( 'ExactMetrics_AMP' ) ) {
|
109 |
+
$options['use_amp_client_id'] = 'true';
|
110 |
+
}
|
111 |
+
|
112 |
+
|
113 |
+
$options['forceSSL'] = 'true';
|
114 |
+
|
115 |
+
// Anonymous data.
|
116 |
+
if ( exactmetrics_get_option( 'anonymize_ips', false ) ) {
|
117 |
+
$options['anonymize_ip'] = 'true';
|
118 |
+
}
|
119 |
+
|
120 |
+
$options = apply_filters( 'exactmetrics_frontend_tracking_options_gtag_before_scripts', $options );
|
121 |
+
|
122 |
+
// Add Enhanced link attribution.
|
123 |
+
if ( exactmetrics_get_option( 'link_attribution', false ) ) {
|
124 |
+
$options['link_attribution'] = 'true';
|
125 |
+
}
|
126 |
+
|
127 |
+
// Add cross-domain tracking.
|
128 |
+
if ( is_array( $cross_domains ) && ! empty( $cross_domains ) ) {
|
129 |
+
$linker_domains = array();
|
130 |
+
foreach ( $cross_domains as $cross_domain ) {
|
131 |
+
if ( ! empty( $cross_domain['domain'] ) ) {
|
132 |
+
$linker_domains[] = $cross_domain['domain'];
|
133 |
+
}
|
134 |
+
}
|
135 |
+
$options['linker'] = array(
|
136 |
+
'domains' => $linker_domains,
|
137 |
+
);
|
138 |
+
}
|
139 |
+
|
140 |
+
if ( exactmetrics_is_debug_mode() ) {
|
141 |
+
$options['debug_mode'] = true;
|
142 |
+
}
|
143 |
+
|
144 |
+
$options = apply_filters( 'exactmetrics_frontend_tracking_options_gtag_before_pageview', $options, $type );
|
145 |
+
$options = apply_filters( 'exactmetrics_frontend_tracking_options_before_pageview', $options, $this->name, $this->version, $type );
|
146 |
+
|
147 |
+
if ( is_404() ) {
|
148 |
+
if ( exactmetrics_get_option( 'hash_tracking', false ) ) {
|
149 |
+
$options['page_path'] = "${placeholder}'/404.html?page=' + document.location.pathname + document.location.search + location.hash + '&from=' + document.referrer${placeholder}";
|
150 |
+
} else {
|
151 |
+
$options['page_path'] = "${placeholder}'/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer${placeholder}";
|
152 |
+
}
|
153 |
+
} else if ( $wp_query->is_search ) {
|
154 |
+
$pushstr = "'/?s=";
|
155 |
+
if ( 0 === (int) $wp_query->found_posts ) {
|
156 |
+
$options['page_path'] = $pushstr . 'no-results:' . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
|
157 |
+
} else if ( (int) $wp_query->found_posts === 1 ) {
|
158 |
+
$options['page_path'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
|
159 |
+
} else if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
|
160 |
+
$options['page_path'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
|
161 |
+
} else {
|
162 |
+
$options['page_path'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
|
163 |
+
}
|
164 |
+
} else if ( exactmetrics_get_option( 'hash_tracking', false ) ) {
|
165 |
+
$options['page_path'] = "${placeholder}location.pathname + location.search + location.hash${placeholder}";
|
166 |
+
}
|
167 |
+
|
168 |
+
$options = apply_filters( 'exactmetrics_frontend_tracking_options_gtag_end', $options, $type );
|
169 |
+
|
170 |
+
if ( $encoded ) {
|
171 |
+
return str_replace(
|
172 |
+
array( '"' . $placeholder, $placeholder . '"' ),
|
173 |
+
'',
|
174 |
+
wp_json_encode( $options )
|
175 |
+
);
|
176 |
+
}
|
177 |
+
|
178 |
+
return $options;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Get frontend output.
|
183 |
+
*
|
184 |
+
* This function is used to return the Javascript
|
185 |
+
* to output in the head of the page for the given
|
186 |
+
* tracking method.
|
187 |
+
*
|
188 |
+
* @return string Javascript to output.
|
189 |
+
* @since 7.15.0
|
190 |
+
* @access public
|
191 |
+
*
|
192 |
+
*/
|
193 |
+
public function frontend_output() {
|
194 |
+
$options = $this->frontend_tracking_options( 'ua', true );
|
195 |
+
$options_v4 = $this->frontend_tracking_options( 'v4', true );
|
196 |
+
$persistent = $this->frontend_tracking_options_persistent();
|
197 |
+
$connected_type = ExactMetrics()->auth->get_connected_type();
|
198 |
+
$v4_id = exactmetrics_get_v4_id_to_output();
|
199 |
+
$ua = exactmetrics_get_ua_to_output();
|
200 |
+
$main_id = $connected_type === 'ua' ? $ua : $v4_id;
|
201 |
+
$src = apply_filters( 'exactmetrics_frontend_output_gtag_src', '//www.googletagmanager.com/gtag/js?id=' . $main_id );
|
202 |
+
$compat_mode = apply_filters( 'exactmetrics_get_option_gtagtracker_compatibility_mode', true );
|
203 |
+
$compat = $compat_mode ? 'window.gtag = __gtagTracker;' : '';
|
204 |
+
$track_user = exactmetrics_track_user();
|
205 |
+
$output = '';
|
206 |
+
$reason = '';
|
207 |
+
$attr_string = exactmetrics_get_frontend_analytics_script_atts();
|
208 |
+
$gtag_async = apply_filters( 'exactmetrics_frontend_gtag_script_async', true ) ? 'async' : '';
|
209 |
+
ob_start();
|
210 |
+
?>
|
211 |
+
<!-- This site uses the Google Analytics by ExactMetrics plugin v<?php echo EXACTMETRICS_VERSION; ?> - Using Analytics tracking - https://www.exactmetrics.com/ -->
|
212 |
+
<?php if ( ! $track_user ) {
|
213 |
+
if ( empty( $v4_id ) && empty( $ua ) ) {
|
214 |
+
$reason = __( 'Note: ExactMetrics is not currently configured on this site. The site owner needs to authenticate with Google Analytics in the ExactMetrics settings panel.', 'google-analytics-dashboard-for-wp' );
|
215 |
+
$output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
|
216 |
+
} else if ( current_user_can( 'exactmetrics_save_settings' ) ) {
|
217 |
+
$reason = __( 'Note: ExactMetrics does not track you as a logged-in site administrator to prevent site owners from accidentally skewing their own Google Analytics data.' . PHP_EOL . 'If you are testing Google Analytics code, please do so either logged out or in the private browsing/incognito mode of your web browser.', 'google-analytics-dashboard-for-wp' );
|
218 |
+
$output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
|
219 |
+
} else {
|
220 |
+
$reason = __( 'Note: The site owner has disabled Google Analytics tracking for your user role.', 'google-analytics-dashboard-for-wp' );
|
221 |
+
$output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
|
222 |
+
}
|
223 |
+
echo $output;
|
224 |
+
} ?>
|
225 |
+
<?php if ( ! empty( $v4_id ) || ! empty( $ua ) ) { ?>
|
226 |
+
<script src="<?php echo esc_attr( $src ); ?>" <?php echo $attr_string; ?> <?php echo esc_attr( $gtag_async ); ?>></script>
|
227 |
+
<script<?php echo $attr_string; ?>>
|
228 |
+
var em_version = '<?php echo EXACTMETRICS_VERSION; ?>';
|
229 |
+
var em_track_user = <?php echo( $track_user ? 'true' : 'false' ); ?>;
|
230 |
+
var em_no_track_reason = <?php echo( $reason ? "'" . esc_js( $reason ) . "'" : "''" ); ?>;
|
231 |
+
<?php do_action( 'exactmetrics_tracking_gtag_frontend_output_after_em_track_user' ); ?>
|
232 |
+
|
233 |
+
<?php if ( $this->should_do_optout() ) { ?>
|
234 |
+
var disableStrs = [
|
235 |
+
<?php if ( ! empty( $v4_id ) ): ?>
|
236 |
+
'ga-disable-<?php echo esc_js( $v4_id ); ?>',
|
237 |
+
<?php endif; ?>
|
238 |
+
<?php if ( ! empty( $ua ) ): ?>
|
239 |
+
'ga-disable-<?php echo esc_js( $ua ); ?>',
|
240 |
+
<?php endif; ?>
|
241 |
+
];
|
242 |
+
|
243 |
+
/* Function to detect opted out users */
|
244 |
+
function __gtagTrackerIsOptedOut() {
|
245 |
+
for ( var index = 0; index < disableStrs.length; index++ ) {
|
246 |
+
if ( document.cookie.indexOf( disableStrs[ index ] + '=true' ) > -1 ) {
|
247 |
+
return true;
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
return false;
|
252 |
+
}
|
253 |
+
|
254 |
+
/* Disable tracking if the opt-out cookie exists. */
|
255 |
+
if ( __gtagTrackerIsOptedOut() ) {
|
256 |
+
for ( var index = 0; index < disableStrs.length; index++ ) {
|
257 |
+
window[ disableStrs[ index ] ] = true;
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
/* Opt-out function */
|
262 |
+
function __gtagTrackerOptout() {
|
263 |
+
for ( var index = 0; index < disableStrs.length; index++ ) {
|
264 |
+
document.cookie = disableStrs[ index ] + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';
|
265 |
+
window[ disableStrs[ index ] ] = true;
|
266 |
+
}
|
267 |
+
}
|
268 |
+
|
269 |
+
if ( 'undefined' === typeof gaOptout ) {
|
270 |
+
function gaOptout() {
|
271 |
+
__gtagTrackerOptout();
|
272 |
+
}
|
273 |
+
}
|
274 |
+
<?php } ?>
|
275 |
+
window.dataLayer = window.dataLayer || [];
|
276 |
+
|
277 |
+
window.ExactMetricsDualTracker = {
|
278 |
+
helpers: {},
|
279 |
+
trackers: {},
|
280 |
+
};
|
281 |
+
if ( em_track_user ) {
|
282 |
+
function __gtagDataLayer() {
|
283 |
+
dataLayer.push( arguments );
|
284 |
+
}
|
285 |
+
|
286 |
+
function __gtagTracker( type, name, parameters ) {
|
287 |
+
if (!parameters) {
|
288 |
+
parameters = {};
|
289 |
+
}
|
290 |
+
|
291 |
+
if (parameters.send_to) {
|
292 |
+
__gtagDataLayer.apply( null, arguments );
|
293 |
+
return;
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( type === 'event' ) {
|
297 |
+
<?php if ( $v4_id ): ?>
|
298 |
+
parameters.send_to = exactmetrics_frontend.v4_id;
|
299 |
+
var hookName = name;
|
300 |
+
if ( typeof parameters[ 'event_category' ] !== 'undefined' ) {
|
301 |
+
hookName = parameters[ 'event_category' ] + ':' + name;
|
302 |
+
}
|
303 |
+
|
304 |
+
if ( typeof ExactMetricsDualTracker.trackers[ hookName ] !== 'undefined' ) {
|
305 |
+
ExactMetricsDualTracker.trackers[ hookName ]( parameters );
|
306 |
+
} else {
|
307 |
+
__gtagDataLayer( 'event', name, parameters );
|
308 |
+
}
|
309 |
+
<?php endif; ?>
|
310 |
+
|
311 |
+
<?php if ( $ua ): ?>
|
312 |
+
parameters.send_to = exactmetrics_frontend.ua;
|
313 |
+
__gtagDataLayer( type, name, parameters );
|
314 |
+
<?php endif; ?>
|
315 |
+
} else {
|
316 |
+
__gtagDataLayer.apply( null, arguments );
|
317 |
+
}
|
318 |
+
}
|
319 |
+
__gtagTracker( 'js', new Date() );
|
320 |
+
__gtagTracker( 'set', {
|
321 |
+
'developer_id.dNDMyYj' : true,
|
322 |
+
<?php
|
323 |
+
if ( ! empty( $persistent ) ) {
|
324 |
+
foreach ( $persistent as $key => $value ) {
|
325 |
+
echo "'" . esc_js( $key ) . "' : '" . esc_js( $value ) . "',";
|
326 |
+
}
|
327 |
+
}
|
328 |
+
?>
|
329 |
+
} );
|
330 |
+
<?php if ( ! empty( $v4_id ) ): ?>
|
331 |
+
__gtagTracker( 'config', '<?php echo esc_js( $v4_id ); ?>', <?php echo $options_v4; ?> );
|
332 |
+
<?php endif; ?>
|
333 |
+
<?php if ( ! empty( $ua ) ): ?>
|
334 |
+
__gtagTracker( 'config', '<?php echo esc_js( $ua ); ?>', <?php echo $options; ?> );
|
335 |
+
<?php
|
336 |
+
endif;
|
337 |
+
/**
|
338 |
+
* Extend or enhance the functionality by adding custom code to frontend
|
339 |
+
* tracking via this hook.
|
340 |
+
*
|
341 |
+
* @since 7.15.0
|
342 |
+
*/
|
343 |
+
do_action( 'exactmetrics_frontend_tracking_gtag_after_pageview' );
|
344 |
+
?>
|
345 |
+
<?php echo esc_js( $compat ); ?>
|
346 |
+
<?php if ( apply_filters( 'exactmetrics_tracking_gtag_frontend_gatracker_compatibility', true ) ) { ?>
|
347 |
+
(
|
348 |
+
function () {
|
349 |
+
/* https://developers.google.com/analytics/devguides/collection/analyticsjs/ */
|
350 |
+
/* ga and __gaTracker compatibility shim. */
|
351 |
+
var noopfn = function () {
|
352 |
+
return null;
|
353 |
+
};
|
354 |
+
var newtracker = function () {
|
355 |
+
return new Tracker();
|
356 |
+
};
|
357 |
+
var Tracker = function () {
|
358 |
+
return null;
|
359 |
+
};
|
360 |
+
var p = Tracker.prototype;
|
361 |
+
p.get = noopfn;
|
362 |
+
p.set = noopfn;
|
363 |
+
p.send = function (){
|
364 |
+
var args = Array.prototype.slice.call(arguments);
|
365 |
+
args.unshift( 'send' );
|
366 |
+
__gaTracker.apply(null, args);
|
367 |
+
};
|
368 |
+
var __gaTracker = function () {
|
369 |
+
var len = arguments.length;
|
370 |
+
if ( len === 0 ) {
|
371 |
+
return;
|
372 |
+
}
|
373 |
+
var f = arguments[len - 1];
|
374 |
+
if ( typeof f !== 'object' || f === null || typeof f.hitCallback !== 'function' ) {
|
375 |
+
if ( 'send' === arguments[0] ) {
|
376 |
+
var hitConverted, hitObject = false, action;
|
377 |
+
if ( 'event' === arguments[1] ) {
|
378 |
+
if ( 'undefined' !== typeof arguments[3] ) {
|
379 |
+
hitObject = {
|
380 |
+
'eventAction': arguments[3],
|
381 |
+
'eventCategory': arguments[2],
|
382 |
+
'eventLabel': arguments[4],
|
383 |
+
'value': arguments[5] ? arguments[5] : 1,
|
384 |
+
}
|
385 |
+
}
|
386 |
+
}
|
387 |
+
if ( 'pageview' === arguments[1] ) {
|
388 |
+
if ( 'undefined' !== typeof arguments[2] ) {
|
389 |
+
hitObject = {
|
390 |
+
'eventAction': 'page_view',
|
391 |
+
'page_path' : arguments[2],
|
392 |
+
}
|
393 |
+
}
|
394 |
+
}
|
395 |
+
if ( typeof arguments[2] === 'object' ) {
|
396 |
+
hitObject = arguments[2];
|
397 |
+
}
|
398 |
+
if ( typeof arguments[5] === 'object' ) {
|
399 |
+
Object.assign( hitObject, arguments[5] );
|
400 |
+
}
|
401 |
+
if ( 'undefined' !== typeof arguments[1].hitType ) {
|
402 |
+
hitObject = arguments[1];
|
403 |
+
if ( 'pageview' === hitObject.hitType ) {
|
404 |
+
hitObject.eventAction = 'page_view';
|
405 |
+
}
|
406 |
+
}
|
407 |
+
if ( hitObject ) {
|
408 |
+
action = 'timing' === arguments[1].hitType ? 'timing_complete' : hitObject.eventAction;
|
409 |
+
hitConverted = mapArgs( hitObject );
|
410 |
+
__gtagTracker( 'event', action, hitConverted );
|
411 |
+
}
|
412 |
+
}
|
413 |
+
return;
|
414 |
+
}
|
415 |
+
|
416 |
+
function mapArgs( args ) {
|
417 |
+
var arg, hit = {};
|
418 |
+
var gaMap = {
|
419 |
+
'eventCategory': 'event_category',
|
420 |
+
'eventAction': 'event_action',
|
421 |
+
'eventLabel': 'event_label',
|
422 |
+
'eventValue': 'event_value',
|
423 |
+
'nonInteraction': 'non_interaction',
|
424 |
+
'timingCategory': 'event_category',
|
425 |
+
'timingVar': 'name',
|
426 |
+
'timingValue': 'value',
|
427 |
+
'timingLabel': 'event_label',
|
428 |
+
'page' : 'page_path',
|
429 |
+
'location' : 'page_location',
|
430 |
+
'title' : 'page_title',
|
431 |
+
};
|
432 |
+
for ( arg in args ) {
|
433 |
+
<?php // Note: we do || instead of && because FBIA can't encode && properly. ?>
|
434 |
+
if ( ! ( ! args.hasOwnProperty(arg) || ! gaMap.hasOwnProperty(arg) ) ) {
|
435 |
+
hit[gaMap[arg]] = args[arg];
|
436 |
+
} else {
|
437 |
+
hit[arg] = args[arg];
|
438 |
+
}
|
439 |
+
}
|
440 |
+
return hit;
|
441 |
+
}
|
442 |
+
|
443 |
+
try {
|
444 |
+
f.hitCallback();
|
445 |
+
} catch ( ex ) {
|
446 |
+
}
|
447 |
+
};
|
448 |
+
__gaTracker.create = newtracker;
|
449 |
+
__gaTracker.getByName = newtracker;
|
450 |
+
__gaTracker.getAll = function () {
|
451 |
+
return [];
|
452 |
+
};
|
453 |
+
__gaTracker.remove = noopfn;
|
454 |
+
__gaTracker.loaded = true;
|
455 |
+
window['__gaTracker'] = __gaTracker;
|
456 |
+
}
|
457 |
+
)();
|
458 |
+
<?php } ?>
|
459 |
+
} else {
|
460 |
+
<?php if ( $this->should_do_optout() ) { ?>
|
461 |
+
console.log( "<?php echo esc_js( $reason );?>" );
|
462 |
+
( function () {
|
463 |
+
function __gtagTracker() {
|
464 |
+
return null;
|
465 |
+
}
|
466 |
+
window['__gtagTracker'] = __gtagTracker;
|
467 |
+
window['gtag'] = __gtagTracker;
|
468 |
+
} )();
|
469 |
+
<?php } ?>
|
470 |
+
}
|
471 |
+
</script>
|
472 |
+
<?php } else { ?>
|
473 |
+
<!-- No UA code set -->
|
474 |
+
<?php } ?>
|
475 |
+
<!-- / Google Analytics by ExactMetrics -->
|
476 |
+
<?php
|
477 |
+
$output = ob_get_contents();
|
478 |
+
ob_end_clean();
|
479 |
+
|
480 |
+
return $output;
|
481 |
+
}
|
482 |
+
|
483 |
+
public function should_do_optout() {
|
484 |
+
return ! ( defined( 'EM_NO_TRACKING_OPTOUT' ) && EM_NO_TRACKING_OPTOUT );
|
485 |
+
}
|
486 |
+
}
|
includes/popular-posts/class-popular-posts-themes.php
CHANGED
@@ -1,850 +1,850 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Popular posts theme-specific functionality.
|
4 |
-
*
|
5 |
-
* @package ExactMetrics
|
6 |
-
*/
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class ExactMetrics_Popular_Posts_Themes
|
10 |
-
*/
|
11 |
-
class ExactMetrics_Popular_Posts_Themes {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* The type of widget to load themes for (inline, widget, products).
|
15 |
-
*
|
16 |
-
* @var string
|
17 |
-
*/
|
18 |
-
public $type;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Holds the array of themes specific to the current type loaded.
|
22 |
-
*
|
23 |
-
* @var array
|
24 |
-
*/
|
25 |
-
public $themes = array();
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Holds the data for the currently selected theme (if indicated in the constructor).
|
29 |
-
*
|
30 |
-
* @var array
|
31 |
-
*/
|
32 |
-
public $theme = array();
|
33 |
-
|
34 |
-
/**
|
35 |
-
* The current theme instance with styles from settings applied.
|
36 |
-
*
|
37 |
-
* @var array
|
38 |
-
*/
|
39 |
-
public $styled_theme;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* The theme options key used to store specific theme styles.
|
43 |
-
*
|
44 |
-
* @var string
|
45 |
-
*/
|
46 |
-
private $themes_styles_key = 'exactmetrics_popular_posts_theme_settings';
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Variable for the theme settings.
|
50 |
-
*
|
51 |
-
* @var array
|
52 |
-
*/
|
53 |
-
private $themes_styles;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* ExactMetrics_Popular_Posts_Themes constructor.
|
57 |
-
*
|
58 |
-
* @param string $type The type of widget: inline/widget/products.
|
59 |
-
* @param string $theme The current theme to load details for.
|
60 |
-
*/
|
61 |
-
public function __construct( $type = 'inline', $theme = '' ) {
|
62 |
-
|
63 |
-
$this->type = $type;
|
64 |
-
if ( method_exists( $this, 'get_themes_' . $type ) ) {
|
65 |
-
$this->themes = call_user_func( array( $this, 'get_themes_' . $type ) );
|
66 |
-
if ( ! empty( $theme ) ) {
|
67 |
-
$this->theme = isset( $this->themes[ $theme ] ) ? $this->themes[ $theme ] : array();
|
68 |
-
|
69 |
-
return $this->theme;
|
70 |
-
} else {
|
71 |
-
return $this->themes;
|
72 |
-
}
|
73 |
-
}
|
74 |
-
|
75 |
-
return false;
|
76 |
-
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Get the current theme details with the option to load properties already styled.
|
81 |
-
*
|
82 |
-
* @return array|mixed
|
83 |
-
*/
|
84 |
-
public function get_theme() {
|
85 |
-
|
86 |
-
return $this->theme;
|
87 |
-
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Get the currently loaded themes for the widget type.
|
92 |
-
*
|
93 |
-
* @return array|mixed
|
94 |
-
*/
|
95 |
-
public function get_themes() {
|
96 |
-
return $this->themes;
|
97 |
-
}
|
98 |
-
|
99 |
-
public function get_theme_stored_styles() {
|
100 |
-
if ( ! isset( $this->themes_styles ) ) {
|
101 |
-
$this->themes_styles = get_option( $this->themes_styles_key, array() );
|
102 |
-
}
|
103 |
-
|
104 |
-
return $this->themes_styles;
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Go through the themes and apply styles from the stored settings.
|
109 |
-
*
|
110 |
-
* @var string $type The instance type: inline/widget/products.
|
111 |
-
* @var array $themes The themes to process/apply styles for.
|
112 |
-
*/
|
113 |
-
public function process_themes_styles( $type, $themes ) {
|
114 |
-
|
115 |
-
$settings = $this->get_theme_stored_styles();
|
116 |
-
|
117 |
-
if ( ! empty( $settings[ $type ] ) ) {
|
118 |
-
foreach ( $themes as $theme_key => $theme_values ) {
|
119 |
-
if ( ! empty( $settings[ $type ][ $theme_key ] ) ) {
|
120 |
-
foreach ( $themes[ $theme_key ]['styles'] as $object => $props ) {
|
121 |
-
if ( ! empty( $settings[ $type ][ $theme_key ][ $object ] ) ) {
|
122 |
-
foreach ( $props as $style_key => $style_value ) {
|
123 |
-
if ( ! empty( $settings[ $type ][ $theme_key ][ $object ][ $style_key ] ) ) {
|
124 |
-
$themes[ $theme_key ]['styles'][ $object ][ $style_key ] = $settings[ $type ][ $theme_key ][ $object ][ $style_key ];
|
125 |
-
}
|
126 |
-
}
|
127 |
-
}
|
128 |
-
}
|
129 |
-
}
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
-
return $themes;
|
134 |
-
|
135 |
-
}
|
136 |
-
|
137 |
-
/**
|
138 |
-
* Get the themes for the inline widget type.
|
139 |
-
*
|
140 |
-
* @return array
|
141 |
-
*/
|
142 |
-
public function get_themes_inline() {
|
143 |
-
|
144 |
-
$themes = array(
|
145 |
-
'alpha' => array(
|
146 |
-
'label' => 'Alpha',
|
147 |
-
'styles' => array(
|
148 |
-
'title' => array(
|
149 |
-
'color' => '#393F4C',
|
150 |
-
'size' => 18,
|
151 |
-
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
152 |
-
),
|
153 |
-
'label' => array(
|
154 |
-
'color' => '#EB5757',
|
155 |
-
'text' => 'Trending',
|
156 |
-
),
|
157 |
-
'background' => array(
|
158 |
-
'color' => '#F0F2F4',
|
159 |
-
),
|
160 |
-
),
|
161 |
-
'level' => 'lite',
|
162 |
-
),
|
163 |
-
'beta' => array(
|
164 |
-
'label' => 'Beta',
|
165 |
-
'styles' => array(
|
166 |
-
'title' => array(
|
167 |
-
'color' => '#393F4C',
|
168 |
-
'size' => 18,
|
169 |
-
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
170 |
-
),
|
171 |
-
'label' => array(
|
172 |
-
'color' => '#EB5757',
|
173 |
-
'text' => 'Trending',
|
174 |
-
),
|
175 |
-
'background' => array(
|
176 |
-
'border' => '#F0F2F4',
|
177 |
-
),
|
178 |
-
'image' => 'theme-preview-beta.png',
|
179 |
-
),
|
180 |
-
'image' => true,
|
181 |
-
'level' => 'lite',
|
182 |
-
),
|
183 |
-
'charlie' => array(
|
184 |
-
'label' => 'Charlie',
|
185 |
-
'styles' => array(
|
186 |
-
'title' => array(
|
187 |
-
'color' => '#393f4c',
|
188 |
-
'size' => 16,
|
189 |
-
),
|
190 |
-
'label' => array(
|
191 |
-
'color' => '#393f4c',
|
192 |
-
'text' => 'Popular Stories Right now',
|
193 |
-
),
|
194 |
-
'border' => array(
|
195 |
-
'color' => '#D3D7DE',
|
196 |
-
),
|
197 |
-
),
|
198 |
-
'list' => array(
|
199 |
-
'15 Proven Ways to Repurpose Content on Your WordPress Site',
|
200 |
-
'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
201 |
-
'How to Set Up Online Ordering for Your Restaurant Website',
|
202 |
-
),
|
203 |
-
'posts' => 3,
|
204 |
-
'level' => 'lite',
|
205 |
-
),
|
206 |
-
'delta' => array(
|
207 |
-
'label' => 'Delta',
|
208 |
-
'styles' => array(
|
209 |
-
'icon' => array(
|
210 |
-
'color' => '#EB5757',
|
211 |
-
),
|
212 |
-
'title' => array(
|
213 |
-
'color' => '#393f4c',
|
214 |
-
'size' => 16,
|
215 |
-
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
216 |
-
),
|
217 |
-
'label' => array(
|
218 |
-
'color' => '#EB5757',
|
219 |
-
'text' => 'Trending',
|
220 |
-
),
|
221 |
-
'background' => array(
|
222 |
-
'border' => '#F0F2F4',
|
223 |
-
),
|
224 |
-
),
|
225 |
-
'level' => 'plus',
|
226 |
-
),
|
227 |
-
'echo' => array(
|
228 |
-
'label' => 'Echo',
|
229 |
-
'styles' => array(
|
230 |
-
'title' => array(
|
231 |
-
'color' => '#393f4c',
|
232 |
-
'size' => 18,
|
233 |
-
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
234 |
-
),
|
235 |
-
'label' => array(
|
236 |
-
'color' => '#EB5757',
|
237 |
-
'text' => 'Trending:',
|
238 |
-
),
|
239 |
-
'background' => array(
|
240 |
-
'color' => '#F0F2F4',
|
241 |
-
),
|
242 |
-
),
|
243 |
-
'level' => 'plus',
|
244 |
-
),
|
245 |
-
'foxtrot' => array(
|
246 |
-
'label' => 'Foxtrot',
|
247 |
-
'styles' => array(
|
248 |
-
'title' => array(
|
249 |
-
'color' => '#393f4c',
|
250 |
-
'size' => 18,
|
251 |
-
'text' => 'How to Build an Email List in WordPress – Email Marketing 101',
|
252 |
-
),
|
253 |
-
'label' => array(
|
254 |
-
'color' => '#EB5757',
|
255 |
-
'text' => 'Trending',
|
256 |
-
),
|
257 |
-
'image' => 'theme-preview-image.jpg',
|
258 |
-
),
|
259 |
-
'image' => true,
|
260 |
-
'level' => 'plus',
|
261 |
-
),
|
262 |
-
'golf' => array(
|
263 |
-
'label' => 'Golf',
|
264 |
-
'styles' => array(
|
265 |
-
'title' => array(
|
266 |
-
'color' => '#393f4c',
|
267 |
-
'size' => 16,
|
268 |
-
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
269 |
-
),
|
270 |
-
'label' => array(
|
271 |
-
'color' => '#EB5757',
|
272 |
-
'text' => 'Popular now',
|
273 |
-
),
|
274 |
-
'border' => array(
|
275 |
-
'color' => '#EB5757',
|
276 |
-
'color2' => '#E2E4E9',
|
277 |
-
),
|
278 |
-
),
|
279 |
-
'level' => 'plus',
|
280 |
-
),
|
281 |
-
'hotel' => array(
|
282 |
-
'label' => 'Hotel',
|
283 |
-
'styles' => array(
|
284 |
-
'title' => array(
|
285 |
-
'color' => '#393f4c',
|
286 |
-
'size' => 18,
|
287 |
-
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
288 |
-
),
|
289 |
-
'icon' => array(
|
290 |
-
'color' => '#EB5757',
|
291 |
-
),
|
292 |
-
),
|
293 |
-
'level' => 'plus',
|
294 |
-
),
|
295 |
-
'india' => array(
|
296 |
-
'label' => 'India',
|
297 |
-
'styles' => array(
|
298 |
-
'title' => array(
|
299 |
-
'color' => '#393f4c',
|
300 |
-
'size' => 14,
|
301 |
-
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
302 |
-
),
|
303 |
-
'label' => array(
|
304 |
-
'color' => '#EB5757',
|
305 |
-
'text' => 'Trending:',
|
306 |
-
),
|
307 |
-
'border' => array(
|
308 |
-
'color' => '#EB5757',
|
309 |
-
),
|
310 |
-
'background' => array(
|
311 |
-
'color' => '#f0f2f4',
|
312 |
-
),
|
313 |
-
),
|
314 |
-
'level' => 'plus',
|
315 |
-
),
|
316 |
-
'juliett' => array(
|
317 |
-
'label' => 'Juliett',
|
318 |
-
'styles' => array(
|
319 |
-
'title' => array(
|
320 |
-
'color' => '#393f4c',
|
321 |
-
'size' => 18,
|
322 |
-
'text' => 'How to Build an Email List in WordPress – Email Marketing 101',
|
323 |
-
),
|
324 |
-
'label' => array(
|
325 |
-
'color' => '#393f4c',
|
326 |
-
'background' => '#e2e4e9',
|
327 |
-
'text' => 'Trending',
|
328 |
-
),
|
329 |
-
'border' => array(
|
330 |
-
'color' => '#e2e4e9',
|
331 |
-
),
|
332 |
-
),
|
333 |
-
'image' => true,
|
334 |
-
'level' => 'plus',
|
335 |
-
),
|
336 |
-
'kilo' => array(
|
337 |
-
'label' => 'Kilo',
|
338 |
-
'styles' => array(
|
339 |
-
'title' => array(
|
340 |
-
'color' => '#393f4c',
|
341 |
-
'size' => 18,
|
342 |
-
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
343 |
-
),
|
344 |
-
'label' => array(
|
345 |
-
'color' => '#EB5757',
|
346 |
-
'text' => 'Popular now',
|
347 |
-
),
|
348 |
-
'border' => array(
|
349 |
-
'color' => '#e2e4e9',
|
350 |
-
'color2' => '#e2e4e9',
|
351 |
-
),
|
352 |
-
),
|
353 |
-
'level' => 'plus',
|
354 |
-
),
|
355 |
-
'lima' => array(
|
356 |
-
'label' => 'Lima',
|
357 |
-
'styles' => array(
|
358 |
-
'title' => array(
|
359 |
-
'color' => '#393f4c',
|
360 |
-
'size' => 18,
|
361 |
-
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
362 |
-
),
|
363 |
-
'label' => array(
|
364 |
-
'color' => '#EB5757',
|
365 |
-
'text' => 'Trending',
|
366 |
-
),
|
367 |
-
'background' => array(
|
368 |
-
'color' => '#f0f2f4',
|
369 |
-
),
|
370 |
-
'image' => 'theme-preview-image-2.jpg',
|
371 |
-
),
|
372 |
-
'image' => true,
|
373 |
-
'level' => 'plus',
|
374 |
-
),
|
375 |
-
'mike' => array(
|
376 |
-
'label' => 'Mike',
|
377 |
-
'styles' => array(
|
378 |
-
'title' => array(
|
379 |
-
'color' => '#393f4c',
|
380 |
-
'size' => 18,
|
381 |
-
'text' => 'How to Build an Email List in WordPress – Email Marketing 101',
|
382 |
-
),
|
383 |
-
'label' => array(
|
384 |
-
'color' => '#fff',
|
385 |
-
'background' => '#f2994a',
|
386 |
-
'text' => 'Trending',
|
387 |
-
),
|
388 |
-
'background' => array(
|
389 |
-
'color' => '#f0f2f4',
|
390 |
-
),
|
391 |
-
'image' => 'theme-preview-image.jpg',
|
392 |
-
),
|
393 |
-
'image' => true,
|
394 |
-
'level' => 'plus',
|
395 |
-
),
|
396 |
-
'november' => array(
|
397 |
-
'label' => 'November',
|
398 |
-
'styles' => array(
|
399 |
-
'title' => array(
|
400 |
-
'color' => '#393f4c',
|
401 |
-
'size' => 16,
|
402 |
-
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
403 |
-
),
|
404 |
-
'label' => array(
|
405 |
-
'color' => '#eb5757',
|
406 |
-
'text' => 'Trending',
|
407 |
-
),
|
408 |
-
'background' => array(
|
409 |
-
'border' => '#f0f2f4',
|
410 |
-
),
|
411 |
-
'icon' => array(
|
412 |
-
'background' => '#eb5757',
|
413 |
-
'color' => '#fff',
|
414 |
-
),
|
415 |
-
),
|
416 |
-
'level' => 'plus',
|
417 |
-
),
|
418 |
-
);
|
419 |
-
|
420 |
-
return $this->process_themes_styles( 'inline', $themes );
|
421 |
-
|
422 |
-
}
|
423 |
-
|
424 |
-
/**
|
425 |
-
* Get the themese for the widget instance.
|
426 |
-
*
|
427 |
-
* @return array
|
428 |
-
*/
|
429 |
-
public function get_themes_widget() {
|
430 |
-
|
431 |
-
$themes = array(
|
432 |
-
'alpha' => array(
|
433 |
-
'label' => 'Alpha',
|
434 |
-
'styles' => array(
|
435 |
-
'title' => array(
|
436 |
-
'color' => '#393F4C',
|
437 |
-
'size' => 16,
|
438 |
-
),
|
439 |
-
'background' => array(
|
440 |
-
'color' => '#F0F2F4',
|
441 |
-
),
|
442 |
-
|
443 |
-
),
|
444 |
-
'list' => array(
|
445 |
-
'items' => array(
|
446 |
-
'How to Set Up WordPress User Activity Tracking in 3 Easy Steps',
|
447 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
448 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
449 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
450 |
-
),
|
451 |
-
),
|
452 |
-
'level' => 'lite',
|
453 |
-
),
|
454 |
-
'beta' => array(
|
455 |
-
'label' => 'Beta',
|
456 |
-
'styles' => array(
|
457 |
-
'title' => array(
|
458 |
-
'color' => '#393F4C',
|
459 |
-
'size' => 16,
|
460 |
-
),
|
461 |
-
'background' => array(
|
462 |
-
'border' => '#1EC185',
|
463 |
-
),
|
464 |
-
),
|
465 |
-
'list' => array(
|
466 |
-
'items' => array(
|
467 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
468 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
469 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
470 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
471 |
-
),
|
472 |
-
),
|
473 |
-
'level' => 'lite',
|
474 |
-
),
|
475 |
-
'charlie' => array(
|
476 |
-
'label' => 'Charlie',
|
477 |
-
'styles' => array(
|
478 |
-
'title' => array(
|
479 |
-
'color' => '#393f4c',
|
480 |
-
'size' => 16,
|
481 |
-
),
|
482 |
-
'background' => array(
|
483 |
-
'color' => '#F0F2F4',
|
484 |
-
'border' => '#338EEF',
|
485 |
-
),
|
486 |
-
),
|
487 |
-
'list' => array(
|
488 |
-
'items' => array(
|
489 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
490 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
491 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
492 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
493 |
-
),
|
494 |
-
),
|
495 |
-
'level' => 'lite',
|
496 |
-
),
|
497 |
-
'delta' => array(
|
498 |
-
'label' => 'Delta',
|
499 |
-
'styles' => array(
|
500 |
-
'title' => array(
|
501 |
-
'color' => '#393f4c',
|
502 |
-
'size' => 18,
|
503 |
-
),
|
504 |
-
'background' => array(
|
505 |
-
'border' => '#D3D7DE',
|
506 |
-
),
|
507 |
-
'meta' => array(
|
508 |
-
'color' => '#99A1B3',
|
509 |
-
'author' => 'on',
|
510 |
-
'date' => 'on',
|
511 |
-
'separator' => '●',
|
512 |
-
),
|
513 |
-
),
|
514 |
-
'list' => array(
|
515 |
-
'items' => array(
|
516 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
517 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
518 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
519 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
520 |
-
),
|
521 |
-
'images' => array(
|
522 |
-
'theme-widget-1.jpg',
|
523 |
-
'theme-widget-2.jpg',
|
524 |
-
'theme-widget-3.jpg',
|
525 |
-
'theme-widget-4.jpg',
|
526 |
-
),
|
527 |
-
),
|
528 |
-
'image' => true,
|
529 |
-
'level' => 'pro',
|
530 |
-
),
|
531 |
-
'echo' => array(
|
532 |
-
'label' => 'Echo',
|
533 |
-
'styles' => array(
|
534 |
-
'title' => array(
|
535 |
-
'color' => '#393f4c',
|
536 |
-
'size' => 16,
|
537 |
-
),
|
538 |
-
'meta' => array(
|
539 |
-
'color' => '#99A1B3',
|
540 |
-
'size' => 12,
|
541 |
-
'author' => 'on',
|
542 |
-
'date' => 'on',
|
543 |
-
'comments' => 'on',
|
544 |
-
'separator' => 'on',
|
545 |
-
),
|
546 |
-
'comments' => array(
|
547 |
-
'color' => '#393F4C',
|
548 |
-
),
|
549 |
-
),
|
550 |
-
'list' => array(
|
551 |
-
'items' => array(
|
552 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
553 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
554 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
555 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
556 |
-
),
|
557 |
-
'images' => array(
|
558 |
-
'theme-widget-5.jpg',
|
559 |
-
'theme-widget-5.jpg',
|
560 |
-
'theme-widget-5.jpg',
|
561 |
-
'theme-widget-5.jpg',
|
562 |
-
),
|
563 |
-
),
|
564 |
-
'image' => true,
|
565 |
-
'level' => 'pro',
|
566 |
-
),
|
567 |
-
'foxtrot' => array(
|
568 |
-
'label' => 'Foxtrot',
|
569 |
-
'styles' => array(
|
570 |
-
'title' => array(
|
571 |
-
'color' => '#393f4c',
|
572 |
-
'size' => 16,
|
573 |
-
),
|
574 |
-
'meta' => array(
|
575 |
-
'color' => '#99A1B3',
|
576 |
-
'size' => 12,
|
577 |
-
'author' => 'on',
|
578 |
-
'date' => 'on',
|
579 |
-
'comments' => 'on',
|
580 |
-
'separator' => '|',
|
581 |
-
),
|
582 |
-
'comments' => array(
|
583 |
-
'color' => '#393F4C',
|
584 |
-
),
|
585 |
-
),
|
586 |
-
'list' => array(
|
587 |
-
'items' => array(
|
588 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
589 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested) ',
|
590 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
591 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
592 |
-
),
|
593 |
-
),
|
594 |
-
'level' => 'pro',
|
595 |
-
),
|
596 |
-
'golf' => array(
|
597 |
-
'label' => 'Golf',
|
598 |
-
'styles' => array(
|
599 |
-
'title' => array(
|
600 |
-
'color' => '#393f4c',
|
601 |
-
'size' => 16,
|
602 |
-
),
|
603 |
-
'label' => array(
|
604 |
-
'color' => '#fff',
|
605 |
-
'background' => '#EB5757',
|
606 |
-
'text' => 'Trending:',
|
607 |
-
'editable' => true,
|
608 |
-
),
|
609 |
-
'meta' => array(
|
610 |
-
'color' => '#99A1B3',
|
611 |
-
'size' => 12,
|
612 |
-
'author' => 'on',
|
613 |
-
'date' => 'on',
|
614 |
-
'comments' => 'on',
|
615 |
-
'separator' => '|',
|
616 |
-
),
|
617 |
-
'comments' => array(
|
618 |
-
'color' => '#393F4C',
|
619 |
-
),
|
620 |
-
),
|
621 |
-
'list' => array(
|
622 |
-
'items' => array(
|
623 |
-
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
624 |
-
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested) ',
|
625 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
626 |
-
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
627 |
-
),
|
628 |
-
),
|
629 |
-
'level' => 'pro',
|
630 |
-
),
|
631 |
-
'hotel' => array(
|
632 |
-
'label' => 'Hotel',
|
633 |
-
'styles' => array(
|
634 |
-
'title' => array(
|
635 |
-
'color' => '#fff',
|
636 |
-
'size' => 16,
|
637 |
-
),
|
638 |
-
'meta' => array(
|
639 |
-
'color' => '#fff',
|
640 |
-
'size' => 12,
|
641 |
-
'author' => 'on',
|
642 |
-
'date' => 'on',
|
643 |
-
),
|
644 |
-
),
|
645 |
-
'list' => array(
|
646 |
-
'items' => array(
|
647 |
-
'How to Allow WordPress to Upload All File Types (The Easy Way)',
|
648 |
-
'14 Handy Google Search Operators for SEO (A Complete List)',
|
649 |
-
'How to Write Irresistible Meta Descriptions for SEO & More Clicks?',
|
650 |
-
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
651 |
-
),
|
652 |
-
'images' => array(
|
653 |
-
'theme-widget-5.jpg',
|
654 |
-
'theme-widget-6.jpg',
|
655 |
-
'theme-widget-7.jpg',
|
656 |
-
'theme-widget-8.jpg',
|
657 |
-
),
|
658 |
-
),
|
659 |
-
'image' => true,
|
660 |
-
'level' => 'pro',
|
661 |
-
),
|
662 |
-
);
|
663 |
-
|
664 |
-
return $this->process_themes_styles( 'widget', $themes );
|
665 |
-
|
666 |
-
}
|
667 |
-
|
668 |
-
/**
|
669 |
-
* Get the themes for the products widget.
|
670 |
-
*
|
671 |
-
* @return array
|
672 |
-
*/
|
673 |
-
public function get_themes_products() {
|
674 |
-
$themes = array(
|
675 |
-
'alpha' => array(
|
676 |
-
'label' => 'Alpha',
|
677 |
-
'styles' => array(
|
678 |
-
'title' => array(
|
679 |
-
'color' => '#393F4C',
|
680 |
-
'size' => 16,
|
681 |
-
),
|
682 |
-
'background' => array(
|
683 |
-
'border' => '#d3d7de',
|
684 |
-
),
|
685 |
-
'price' => array(
|
686 |
-
'color' => '#393F4C',
|
687 |
-
'size' => 12,
|
688 |
-
),
|
689 |
-
'rating' => array(
|
690 |
-
'color' => '#EB5757',
|
691 |
-
),
|
692 |
-
'meta' => array(
|
693 |
-
'price' => 'on',
|
694 |
-
'rating' => 'on',
|
695 |
-
'image' => 'on',
|
696 |
-
),
|
697 |
-
),
|
698 |
-
'list' => array(
|
699 |
-
'items' => array(
|
700 |
-
'WPBeginner 10-Year Anniversary Gray T-Shirt',
|
701 |
-
'WPForms Small White Logo T-Shirt',
|
702 |
-
'OptinMonster White Text Color Mascot T-Shirt',
|
703 |
-
'WPForms Make Things Simple Gray T-Shirt',
|
704 |
-
),
|
705 |
-
'images' => array(
|
706 |
-
'theme-products-1.jpg',
|
707 |
-
'theme-products-2.jpg',
|
708 |
-
'theme-products-3.jpg',
|
709 |
-
'theme-products-4.jpg',
|
710 |
-
),
|
711 |
-
'prices' => array(
|
712 |
-
'$59.99',
|
713 |
-
'$28.00',
|
714 |
-
'$65.00',
|
715 |
-
'$59.50',
|
716 |
-
),
|
717 |
-
),
|
718 |
-
),
|
719 |
-
'beta' => array(
|
720 |
-
'label' => 'Beta',
|
721 |
-
'styles' => array(
|
722 |
-
'title' => array(
|
723 |
-
'color' => '#393F4C',
|
724 |
-
'size' => 16,
|
725 |
-
),
|
726 |
-
'background' => array(
|
727 |
-
'color' => '#F0F2F4',
|
728 |
-
),
|
729 |
-
'price' => array(
|
730 |
-
'color' => '#4C5566',
|
731 |
-
'size' => 12,
|
732 |
-
),
|
733 |
-
'rating' => array(
|
734 |
-
'color' => '#F2D74A',
|
735 |
-
),
|
736 |
-
'meta' => array(
|
737 |
-
'price' => 'on',
|
738 |
-
'rating' => 'on',
|
739 |
-
'image' => 'on',
|
740 |
-
),
|
741 |
-
),
|
742 |
-
'list' => array(
|
743 |
-
'items' => array(
|
744 |
-
'Admin WPBeginner Black T-Shirt',
|
745 |
-
'Black WP Beginner logo T-Shirt',
|
746 |
-
'Technically Awesome Groovy White T-Shirt',
|
747 |
-
'Technically Awesome Code Comment Black T-Shirt',
|
748 |
-
),
|
749 |
-
'images' => array(
|
750 |
-
'theme-products-5.jpg',
|
751 |
-
'theme-products-7.jpg',
|
752 |
-
'theme-products-6.jpg',
|
753 |
-
'theme-products-8.jpg',
|
754 |
-
),
|
755 |
-
'prices' => array(
|
756 |
-
'$29.50',
|
757 |
-
'$28.00',
|
758 |
-
'$65.00',
|
759 |
-
'$59.50',
|
760 |
-
),
|
761 |
-
),
|
762 |
-
),
|
763 |
-
'charlie' => array(
|
764 |
-
'label' => 'Charlie',
|
765 |
-
'styles' => array(
|
766 |
-
'title' => array(
|
767 |
-
'color' => '#fff',
|
768 |
-
'size' => 16,
|
769 |
-
),
|
770 |
-
'rating' => array(
|
771 |
-
'color' => '#F2D74A',
|
772 |
-
),
|
773 |
-
'price' => array(
|
774 |
-
'color' => '#fff',
|
775 |
-
'size' => 12,
|
776 |
-
),
|
777 |
-
'meta' => array(
|
778 |
-
'price' => 'on',
|
779 |
-
'rating' => 'on',
|
780 |
-
),
|
781 |
-
),
|
782 |
-
'list' => array(
|
783 |
-
'items' => array(
|
784 |
-
'Admin WPBeginner Black T-Shirt',
|
785 |
-
'Black WP Beginner logo T-Shirt',
|
786 |
-
'Technically Awesome Groovy White T-Shirt',
|
787 |
-
'Technically Awesome Code Comment Black T-Shirt',
|
788 |
-
),
|
789 |
-
'images' => array(
|
790 |
-
'theme-products-5.jpg',
|
791 |
-
'theme-products-7.jpg',
|
792 |
-
'theme-products-6.jpg',
|
793 |
-
'theme-products-8.jpg',
|
794 |
-
),
|
795 |
-
'prices' => array(
|
796 |
-
'$29.50',
|
797 |
-
'$28.00',
|
798 |
-
'$65.00',
|
799 |
-
'$59.50',
|
800 |
-
),
|
801 |
-
),
|
802 |
-
'image' => true,
|
803 |
-
),
|
804 |
-
'delta' => array(
|
805 |
-
'label' => 'Delta',
|
806 |
-
'styles' => array(
|
807 |
-
'title' => array(
|
808 |
-
'color' => '#393f4c',
|
809 |
-
'size' => 14,
|
810 |
-
),
|
811 |
-
'rating' => array(
|
812 |
-
'color' => '#F2D74A',
|
813 |
-
),
|
814 |
-
'price' => array(
|
815 |
-
'color' => '#4C5566',
|
816 |
-
'size' => 12,
|
817 |
-
),
|
818 |
-
'meta' => array(
|
819 |
-
'price' => 'on',
|
820 |
-
'rating' => 'on',
|
821 |
-
'image' => 'on',
|
822 |
-
),
|
823 |
-
),
|
824 |
-
'list' => array(
|
825 |
-
'items' => array(
|
826 |
-
'Admin WPBeginner Black T-Shirt',
|
827 |
-
'Black WP Beginner logo T-Shirt',
|
828 |
-
'Technically Awesome Groovy White T-Shirt',
|
829 |
-
'Technically Awesome Code Comment Black T-Shirt',
|
830 |
-
),
|
831 |
-
'images' => array(
|
832 |
-
'theme-products-5.jpg',
|
833 |
-
'theme-products-7.jpg',
|
834 |
-
'theme-products-6.jpg',
|
835 |
-
'theme-products-8.jpg',
|
836 |
-
),
|
837 |
-
'prices' => array(
|
838 |
-
'$29.50',
|
839 |
-
'$28.00',
|
840 |
-
'$65.00',
|
841 |
-
'$59.50',
|
842 |
-
),
|
843 |
-
),
|
844 |
-
),
|
845 |
-
);
|
846 |
-
|
847 |
-
return $this->process_themes_styles( 'products', $themes );
|
848 |
-
}
|
849 |
-
|
850 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Popular posts theme-specific functionality.
|
4 |
+
*
|
5 |
+
* @package ExactMetrics
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class ExactMetrics_Popular_Posts_Themes
|
10 |
+
*/
|
11 |
+
class ExactMetrics_Popular_Posts_Themes {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The type of widget to load themes for (inline, widget, products).
|
15 |
+
*
|
16 |
+
* @var string
|
17 |
+
*/
|
18 |
+
public $type;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Holds the array of themes specific to the current type loaded.
|
22 |
+
*
|
23 |
+
* @var array
|
24 |
+
*/
|
25 |
+
public $themes = array();
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Holds the data for the currently selected theme (if indicated in the constructor).
|
29 |
+
*
|
30 |
+
* @var array
|
31 |
+
*/
|
32 |
+
public $theme = array();
|
33 |
+
|
34 |
+
/**
|
35 |
+
* The current theme instance with styles from settings applied.
|
36 |
+
*
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
public $styled_theme;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* The theme options key used to store specific theme styles.
|
43 |
+
*
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
private $themes_styles_key = 'exactmetrics_popular_posts_theme_settings';
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Variable for the theme settings.
|
50 |
+
*
|
51 |
+
* @var array
|
52 |
+
*/
|
53 |
+
private $themes_styles;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* ExactMetrics_Popular_Posts_Themes constructor.
|
57 |
+
*
|
58 |
+
* @param string $type The type of widget: inline/widget/products.
|
59 |
+
* @param string $theme The current theme to load details for.
|
60 |
+
*/
|
61 |
+
public function __construct( $type = 'inline', $theme = '' ) {
|
62 |
+
|
63 |
+
$this->type = $type;
|
64 |
+
if ( method_exists( $this, 'get_themes_' . $type ) ) {
|
65 |
+
$this->themes = call_user_func( array( $this, 'get_themes_' . $type ) );
|
66 |
+
if ( ! empty( $theme ) ) {
|
67 |
+
$this->theme = isset( $this->themes[ $theme ] ) ? $this->themes[ $theme ] : array();
|
68 |
+
|
69 |
+
return $this->theme;
|
70 |
+
} else {
|
71 |
+
return $this->themes;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
return false;
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Get the current theme details with the option to load properties already styled.
|
81 |
+
*
|
82 |
+
* @return array|mixed
|
83 |
+
*/
|
84 |
+
public function get_theme() {
|
85 |
+
|
86 |
+
return $this->theme;
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get the currently loaded themes for the widget type.
|
92 |
+
*
|
93 |
+
* @return array|mixed
|
94 |
+
*/
|
95 |
+
public function get_themes() {
|
96 |
+
return $this->themes;
|
97 |
+
}
|
98 |
+
|
99 |
+
public function get_theme_stored_styles() {
|
100 |
+
if ( ! isset( $this->themes_styles ) ) {
|
101 |
+
$this->themes_styles = get_option( $this->themes_styles_key, array() );
|
102 |
+
}
|
103 |
+
|
104 |
+
return $this->themes_styles;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Go through the themes and apply styles from the stored settings.
|
109 |
+
*
|
110 |
+
* @var string $type The instance type: inline/widget/products.
|
111 |
+
* @var array $themes The themes to process/apply styles for.
|
112 |
+
*/
|
113 |
+
public function process_themes_styles( $type, $themes ) {
|
114 |
+
|
115 |
+
$settings = $this->get_theme_stored_styles();
|
116 |
+
|
117 |
+
if ( ! empty( $settings[ $type ] ) ) {
|
118 |
+
foreach ( $themes as $theme_key => $theme_values ) {
|
119 |
+
if ( ! empty( $settings[ $type ][ $theme_key ] ) ) {
|
120 |
+
foreach ( $themes[ $theme_key ]['styles'] as $object => $props ) {
|
121 |
+
if ( ! empty( $settings[ $type ][ $theme_key ][ $object ] ) ) {
|
122 |
+
foreach ( $props as $style_key => $style_value ) {
|
123 |
+
if ( ! empty( $settings[ $type ][ $theme_key ][ $object ][ $style_key ] ) ) {
|
124 |
+
$themes[ $theme_key ]['styles'][ $object ][ $style_key ] = $settings[ $type ][ $theme_key ][ $object ][ $style_key ];
|
125 |
+
}
|
126 |
+
}
|
127 |
+
}
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
return $themes;
|
134 |
+
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Get the themes for the inline widget type.
|
139 |
+
*
|
140 |
+
* @return array
|
141 |
+
*/
|
142 |
+
public function get_themes_inline() {
|
143 |
+
|
144 |
+
$themes = array(
|
145 |
+
'alpha' => array(
|
146 |
+
'label' => 'Alpha',
|
147 |
+
'styles' => array(
|
148 |
+
'title' => array(
|
149 |
+
'color' => '#393F4C',
|
150 |
+
'size' => 18,
|
151 |
+
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
152 |
+
),
|
153 |
+
'label' => array(
|
154 |
+
'color' => '#EB5757',
|
155 |
+
'text' => 'Trending',
|
156 |
+
),
|
157 |
+
'background' => array(
|
158 |
+
'color' => '#F0F2F4',
|
159 |
+
),
|
160 |
+
),
|
161 |
+
'level' => 'lite',
|
162 |
+
),
|
163 |
+
'beta' => array(
|
164 |
+
'label' => 'Beta',
|
165 |
+
'styles' => array(
|
166 |
+
'title' => array(
|
167 |
+
'color' => '#393F4C',
|
168 |
+
'size' => 18,
|
169 |
+
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
170 |
+
),
|
171 |
+
'label' => array(
|
172 |
+
'color' => '#EB5757',
|
173 |
+
'text' => 'Trending',
|
174 |
+
),
|
175 |
+
'background' => array(
|
176 |
+
'border' => '#F0F2F4',
|
177 |
+
),
|
178 |
+
'image' => 'theme-preview-beta.png',
|
179 |
+
),
|
180 |
+
'image' => true,
|
181 |
+
'level' => 'lite',
|
182 |
+
),
|
183 |
+
'charlie' => array(
|
184 |
+
'label' => 'Charlie',
|
185 |
+
'styles' => array(
|
186 |
+
'title' => array(
|
187 |
+
'color' => '#393f4c',
|
188 |
+
'size' => 16,
|
189 |
+
),
|
190 |
+
'label' => array(
|
191 |
+
'color' => '#393f4c',
|
192 |
+
'text' => 'Popular Stories Right now',
|
193 |
+
),
|
194 |
+
'border' => array(
|
195 |
+
'color' => '#D3D7DE',
|
196 |
+
),
|
197 |
+
),
|
198 |
+
'list' => array(
|
199 |
+
'15 Proven Ways to Repurpose Content on Your WordPress Site',
|
200 |
+
'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
201 |
+
'How to Set Up Online Ordering for Your Restaurant Website',
|
202 |
+
),
|
203 |
+
'posts' => 3,
|
204 |
+
'level' => 'lite',
|
205 |
+
),
|
206 |
+
'delta' => array(
|
207 |
+
'label' => 'Delta',
|
208 |
+
'styles' => array(
|
209 |
+
'icon' => array(
|
210 |
+
'color' => '#EB5757',
|
211 |
+
),
|
212 |
+
'title' => array(
|
213 |
+
'color' => '#393f4c',
|
214 |
+
'size' => 16,
|
215 |
+
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
216 |
+
),
|
217 |
+
'label' => array(
|
218 |
+
'color' => '#EB5757',
|
219 |
+
'text' => 'Trending',
|
220 |
+
),
|
221 |
+
'background' => array(
|
222 |
+
'border' => '#F0F2F4',
|
223 |
+
),
|
224 |
+
),
|
225 |
+
'level' => 'plus',
|
226 |
+
),
|
227 |
+
'echo' => array(
|
228 |
+
'label' => 'Echo',
|
229 |
+
'styles' => array(
|
230 |
+
'title' => array(
|
231 |
+
'color' => '#393f4c',
|
232 |
+
'size' => 18,
|
233 |
+
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
234 |
+
),
|
235 |
+
'label' => array(
|
236 |
+
'color' => '#EB5757',
|
237 |
+
'text' => 'Trending:',
|
238 |
+
),
|
239 |
+
'background' => array(
|
240 |
+
'color' => '#F0F2F4',
|
241 |
+
),
|
242 |
+
),
|
243 |
+
'level' => 'plus',
|
244 |
+
),
|
245 |
+
'foxtrot' => array(
|
246 |
+
'label' => 'Foxtrot',
|
247 |
+
'styles' => array(
|
248 |
+
'title' => array(
|
249 |
+
'color' => '#393f4c',
|
250 |
+
'size' => 18,
|
251 |
+
'text' => 'How to Build an Email List in WordPress – Email Marketing 101',
|
252 |
+
),
|
253 |
+
'label' => array(
|
254 |
+
'color' => '#EB5757',
|
255 |
+
'text' => 'Trending',
|
256 |
+
),
|
257 |
+
'image' => 'theme-preview-image.jpg',
|
258 |
+
),
|
259 |
+
'image' => true,
|
260 |
+
'level' => 'plus',
|
261 |
+
),
|
262 |
+
'golf' => array(
|
263 |
+
'label' => 'Golf',
|
264 |
+
'styles' => array(
|
265 |
+
'title' => array(
|
266 |
+
'color' => '#393f4c',
|
267 |
+
'size' => 16,
|
268 |
+
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
269 |
+
),
|
270 |
+
'label' => array(
|
271 |
+
'color' => '#EB5757',
|
272 |
+
'text' => 'Popular now',
|
273 |
+
),
|
274 |
+
'border' => array(
|
275 |
+
'color' => '#EB5757',
|
276 |
+
'color2' => '#E2E4E9',
|
277 |
+
),
|
278 |
+
),
|
279 |
+
'level' => 'plus',
|
280 |
+
),
|
281 |
+
'hotel' => array(
|
282 |
+
'label' => 'Hotel',
|
283 |
+
'styles' => array(
|
284 |
+
'title' => array(
|
285 |
+
'color' => '#393f4c',
|
286 |
+
'size' => 18,
|
287 |
+
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
288 |
+
),
|
289 |
+
'icon' => array(
|
290 |
+
'color' => '#EB5757',
|
291 |
+
),
|
292 |
+
),
|
293 |
+
'level' => 'plus',
|
294 |
+
),
|
295 |
+
'india' => array(
|
296 |
+
'label' => 'India',
|
297 |
+
'styles' => array(
|
298 |
+
'title' => array(
|
299 |
+
'color' => '#393f4c',
|
300 |
+
'size' => 14,
|
301 |
+
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
302 |
+
),
|
303 |
+
'label' => array(
|
304 |
+
'color' => '#EB5757',
|
305 |
+
'text' => 'Trending:',
|
306 |
+
),
|
307 |
+
'border' => array(
|
308 |
+
'color' => '#EB5757',
|
309 |
+
),
|
310 |
+
'background' => array(
|
311 |
+
'color' => '#f0f2f4',
|
312 |
+
),
|
313 |
+
),
|
314 |
+
'level' => 'plus',
|
315 |
+
),
|
316 |
+
'juliett' => array(
|
317 |
+
'label' => 'Juliett',
|
318 |
+
'styles' => array(
|
319 |
+
'title' => array(
|
320 |
+
'color' => '#393f4c',
|
321 |
+
'size' => 18,
|
322 |
+
'text' => 'How to Build an Email List in WordPress – Email Marketing 101',
|
323 |
+
),
|
324 |
+
'label' => array(
|
325 |
+
'color' => '#393f4c',
|
326 |
+
'background' => '#e2e4e9',
|
327 |
+
'text' => 'Trending',
|
328 |
+
),
|
329 |
+
'border' => array(
|
330 |
+
'color' => '#e2e4e9',
|
331 |
+
),
|
332 |
+
),
|
333 |
+
'image' => true,
|
334 |
+
'level' => 'plus',
|
335 |
+
),
|
336 |
+
'kilo' => array(
|
337 |
+
'label' => 'Kilo',
|
338 |
+
'styles' => array(
|
339 |
+
'title' => array(
|
340 |
+
'color' => '#393f4c',
|
341 |
+
'size' => 18,
|
342 |
+
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
343 |
+
),
|
344 |
+
'label' => array(
|
345 |
+
'color' => '#EB5757',
|
346 |
+
'text' => 'Popular now',
|
347 |
+
),
|
348 |
+
'border' => array(
|
349 |
+
'color' => '#e2e4e9',
|
350 |
+
'color2' => '#e2e4e9',
|
351 |
+
),
|
352 |
+
),
|
353 |
+
'level' => 'plus',
|
354 |
+
),
|
355 |
+
'lima' => array(
|
356 |
+
'label' => 'Lima',
|
357 |
+
'styles' => array(
|
358 |
+
'title' => array(
|
359 |
+
'color' => '#393f4c',
|
360 |
+
'size' => 18,
|
361 |
+
'text' => '15 Proven Ways to Repurpose Content on Your WordPress Site',
|
362 |
+
),
|
363 |
+
'label' => array(
|
364 |
+
'color' => '#EB5757',
|
365 |
+
'text' => 'Trending',
|
366 |
+
),
|
367 |
+
'background' => array(
|
368 |
+
'color' => '#f0f2f4',
|
369 |
+
),
|
370 |
+
'image' => 'theme-preview-image-2.jpg',
|
371 |
+
),
|
372 |
+
'image' => true,
|
373 |
+
'level' => 'plus',
|
374 |
+
),
|
375 |
+
'mike' => array(
|
376 |
+
'label' => 'Mike',
|
377 |
+
'styles' => array(
|
378 |
+
'title' => array(
|
379 |
+
'color' => '#393f4c',
|
380 |
+
'size' => 18,
|
381 |
+
'text' => 'How to Build an Email List in WordPress – Email Marketing 101',
|
382 |
+
),
|
383 |
+
'label' => array(
|
384 |
+
'color' => '#fff',
|
385 |
+
'background' => '#f2994a',
|
386 |
+
'text' => 'Trending',
|
387 |
+
),
|
388 |
+
'background' => array(
|
389 |
+
'color' => '#f0f2f4',
|
390 |
+
),
|
391 |
+
'image' => 'theme-preview-image.jpg',
|
392 |
+
),
|
393 |
+
'image' => true,
|
394 |
+
'level' => 'plus',
|
395 |
+
),
|
396 |
+
'november' => array(
|
397 |
+
'label' => 'November',
|
398 |
+
'styles' => array(
|
399 |
+
'title' => array(
|
400 |
+
'color' => '#393f4c',
|
401 |
+
'size' => 16,
|
402 |
+
'text' => 'How to Use Google Trends to Boost Traffic and Sales (9 Simple Ways)',
|
403 |
+
),
|
404 |
+
'label' => array(
|
405 |
+
'color' => '#eb5757',
|
406 |
+
'text' => 'Trending',
|
407 |
+
),
|
408 |
+
'background' => array(
|
409 |
+
'border' => '#f0f2f4',
|
410 |
+
),
|
411 |
+
'icon' => array(
|
412 |
+
'background' => '#eb5757',
|
413 |
+
'color' => '#fff',
|
414 |
+
),
|
415 |
+
),
|
416 |
+
'level' => 'plus',
|
417 |
+
),
|
418 |
+
);
|
419 |
+
|
420 |
+
return $this->process_themes_styles( 'inline', $themes );
|
421 |
+
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Get the themese for the widget instance.
|
426 |
+
*
|
427 |
+
* @return array
|
428 |
+
*/
|
429 |
+
public function get_themes_widget() {
|
430 |
+
|
431 |
+
$themes = array(
|
432 |
+
'alpha' => array(
|
433 |
+
'label' => 'Alpha',
|
434 |
+
'styles' => array(
|
435 |
+
'title' => array(
|
436 |
+
'color' => '#393F4C',
|
437 |
+
'size' => 16,
|
438 |
+
),
|
439 |
+
'background' => array(
|
440 |
+
'color' => '#F0F2F4',
|
441 |
+
),
|
442 |
+
|
443 |
+
),
|
444 |
+
'list' => array(
|
445 |
+
'items' => array(
|
446 |
+
'How to Set Up WordPress User Activity Tracking in 3 Easy Steps',
|
447 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
448 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
449 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
450 |
+
),
|
451 |
+
),
|
452 |
+
'level' => 'lite',
|
453 |
+
),
|
454 |
+
'beta' => array(
|
455 |
+
'label' => 'Beta',
|
456 |
+
'styles' => array(
|
457 |
+
'title' => array(
|
458 |
+
'color' => '#393F4C',
|
459 |
+
'size' => 16,
|
460 |
+
),
|
461 |
+
'background' => array(
|
462 |
+
'border' => '#1EC185',
|
463 |
+
),
|
464 |
+
),
|
465 |
+
'list' => array(
|
466 |
+
'items' => array(
|
467 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
468 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
469 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
470 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
471 |
+
),
|
472 |
+
),
|
473 |
+
'level' => 'lite',
|
474 |
+
),
|
475 |
+
'charlie' => array(
|
476 |
+
'label' => 'Charlie',
|
477 |
+
'styles' => array(
|
478 |
+
'title' => array(
|
479 |
+
'color' => '#393f4c',
|
480 |
+
'size' => 16,
|
481 |
+
),
|
482 |
+
'background' => array(
|
483 |
+
'color' => '#F0F2F4',
|
484 |
+
'border' => '#338EEF',
|
485 |
+
),
|
486 |
+
),
|
487 |
+
'list' => array(
|
488 |
+
'items' => array(
|
489 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
490 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
491 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
492 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
493 |
+
),
|
494 |
+
),
|
495 |
+
'level' => 'lite',
|
496 |
+
),
|
497 |
+
'delta' => array(
|
498 |
+
'label' => 'Delta',
|
499 |
+
'styles' => array(
|
500 |
+
'title' => array(
|
501 |
+
'color' => '#393f4c',
|
502 |
+
'size' => 18,
|
503 |
+
),
|
504 |
+
'background' => array(
|
505 |
+
'border' => '#D3D7DE',
|
506 |
+
),
|
507 |
+
'meta' => array(
|
508 |
+
'color' => '#99A1B3',
|
509 |
+
'author' => 'on',
|
510 |
+
'date' => 'on',
|
511 |
+
'separator' => '●',
|
512 |
+
),
|
513 |
+
),
|
514 |
+
'list' => array(
|
515 |
+
'items' => array(
|
516 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
517 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
518 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
519 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
520 |
+
),
|
521 |
+
'images' => array(
|
522 |
+
'theme-widget-1.jpg',
|
523 |
+
'theme-widget-2.jpg',
|
524 |
+
'theme-widget-3.jpg',
|
525 |
+
'theme-widget-4.jpg',
|
526 |
+
),
|
527 |
+
),
|
528 |
+
'image' => true,
|
529 |
+
'level' => 'pro',
|
530 |
+
),
|
531 |
+
'echo' => array(
|
532 |
+
'label' => 'Echo',
|
533 |
+
'styles' => array(
|
534 |
+
'title' => array(
|
535 |
+
'color' => '#393f4c',
|
536 |
+
'size' => 16,
|
537 |
+
),
|
538 |
+
'meta' => array(
|
539 |
+
'color' => '#99A1B3',
|
540 |
+
'size' => 12,
|
541 |
+
'author' => 'on',
|
542 |
+
'date' => 'on',
|
543 |
+
'comments' => 'on',
|
544 |
+
'separator' => 'on',
|
545 |
+
),
|
546 |
+
'comments' => array(
|
547 |
+
'color' => '#393F4C',
|
548 |
+
),
|
549 |
+
),
|
550 |
+
'list' => array(
|
551 |
+
'items' => array(
|
552 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
553 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
554 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested)',
|
555 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
556 |
+
),
|
557 |
+
'images' => array(
|
558 |
+
'theme-widget-5.jpg',
|
559 |
+
'theme-widget-5.jpg',
|
560 |
+
'theme-widget-5.jpg',
|
561 |
+
'theme-widget-5.jpg',
|
562 |
+
),
|
563 |
+
),
|
564 |
+
'image' => true,
|
565 |
+
'level' => 'pro',
|
566 |
+
),
|
567 |
+
'foxtrot' => array(
|
568 |
+
'label' => 'Foxtrot',
|
569 |
+
'styles' => array(
|
570 |
+
'title' => array(
|
571 |
+
'color' => '#393f4c',
|
572 |
+
'size' => 16,
|
573 |
+
),
|
574 |
+
'meta' => array(
|
575 |
+
'color' => '#99A1B3',
|
576 |
+
'size' => 12,
|
577 |
+
'author' => 'on',
|
578 |
+
'date' => 'on',
|
579 |
+
'comments' => 'on',
|
580 |
+
'separator' => '|',
|
581 |
+
),
|
582 |
+
'comments' => array(
|
583 |
+
'color' => '#393F4C',
|
584 |
+
),
|
585 |
+
),
|
586 |
+
'list' => array(
|
587 |
+
'items' => array(
|
588 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
589 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested) ',
|
590 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
591 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
592 |
+
),
|
593 |
+
),
|
594 |
+
'level' => 'pro',
|
595 |
+
),
|
596 |
+
'golf' => array(
|
597 |
+
'label' => 'Golf',
|
598 |
+
'styles' => array(
|
599 |
+
'title' => array(
|
600 |
+
'color' => '#393f4c',
|
601 |
+
'size' => 16,
|
602 |
+
),
|
603 |
+
'label' => array(
|
604 |
+
'color' => '#fff',
|
605 |
+
'background' => '#EB5757',
|
606 |
+
'text' => 'Trending:',
|
607 |
+
'editable' => true,
|
608 |
+
),
|
609 |
+
'meta' => array(
|
610 |
+
'color' => '#99A1B3',
|
611 |
+
'size' => 12,
|
612 |
+
'author' => 'on',
|
613 |
+
'date' => 'on',
|
614 |
+
'comments' => 'on',
|
615 |
+
'separator' => '|',
|
616 |
+
),
|
617 |
+
'comments' => array(
|
618 |
+
'color' => '#393F4C',
|
619 |
+
),
|
620 |
+
),
|
621 |
+
'list' => array(
|
622 |
+
'items' => array(
|
623 |
+
'9 Proven Ways to Get Google to Index Your Website Right Away',
|
624 |
+
'12 Best Social Media Analytics Tools for Marketers (Tried & Tested) ',
|
625 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
626 |
+
'How to Share Your Google Analytics Reports with Others (5 Easy Ways)',
|
627 |
+
),
|
628 |
+
),
|
629 |
+
'level' => 'pro',
|
630 |
+
),
|
631 |
+
'hotel' => array(
|
632 |
+
'label' => 'Hotel',
|
633 |
+
'styles' => array(
|
634 |
+
'title' => array(
|
635 |
+
'color' => '#fff',
|
636 |
+
'size' => 16,
|
637 |
+
),
|
638 |
+
'meta' => array(
|
639 |
+
'color' => '#fff',
|
640 |
+
'size' => 12,
|
641 |
+
'author' => 'on',
|
642 |
+
'date' => 'on',
|
643 |
+
),
|
644 |
+
),
|
645 |
+
'list' => array(
|
646 |
+
'items' => array(
|
647 |
+
'How to Allow WordPress to Upload All File Types (The Easy Way)',
|
648 |
+
'14 Handy Google Search Operators for SEO (A Complete List)',
|
649 |
+
'How to Write Irresistible Meta Descriptions for SEO & More Clicks?',
|
650 |
+
'Uncover How Much Traffic Does a Website Get (5 Effortless Ways)',
|
651 |
+
),
|
652 |
+
'images' => array(
|
653 |
+
'theme-widget-5.jpg',
|
654 |
+
'theme-widget-6.jpg',
|
655 |
+
'theme-widget-7.jpg',
|
656 |
+
'theme-widget-8.jpg',
|
657 |
+
),
|
658 |
+
),
|
659 |
+
'image' => true,
|
660 |
+
'level' => 'pro',
|
661 |
+
),
|
662 |
+
);
|
663 |
+
|
664 |
+
return $this->process_themes_styles( 'widget', $themes );
|
665 |
+
|
666 |
+
}
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Get the themes for the products widget.
|
670 |
+
*
|
671 |
+
* @return array
|
672 |
+
*/
|
673 |
+
public function get_themes_products() {
|
674 |
+
$themes = array(
|
675 |
+
'alpha' => array(
|
676 |
+
'label' => 'Alpha',
|
677 |
+
'styles' => array(
|
678 |
+
'title' => array(
|
679 |
+
'color' => '#393F4C',
|
680 |
+
'size' => 16,
|
681 |
+
),
|
682 |
+
'background' => array(
|
683 |
+
'border' => '#d3d7de',
|
684 |
+
),
|
685 |
+
'price' => array(
|
686 |
+
'color' => '#393F4C',
|
687 |
+
'size' => 12,
|
688 |
+
),
|
689 |
+
'rating' => array(
|
690 |
+
'color' => '#EB5757',
|
691 |
+
),
|
692 |
+
'meta' => array(
|
693 |
+
'price' => 'on',
|
694 |
+
'rating' => 'on',
|
695 |
+
'image' => 'on',
|
696 |
+
),
|
697 |
+
),
|
698 |
+
'list' => array(
|
699 |
+
'items' => array(
|
700 |
+
'WPBeginner 10-Year Anniversary Gray T-Shirt',
|
701 |
+
'WPForms Small White Logo T-Shirt',
|
702 |
+
'OptinMonster White Text Color Mascot T-Shirt',
|
703 |
+
'WPForms Make Things Simple Gray T-Shirt',
|
704 |
+
),
|
705 |
+
'images' => array(
|
706 |
+
'theme-products-1.jpg',
|
707 |
+
'theme-products-2.jpg',
|
708 |
+
'theme-products-3.jpg',
|
709 |
+
'theme-products-4.jpg',
|
710 |
+
),
|
711 |
+
'prices' => array(
|
712 |
+
'$59.99',
|
713 |
+
'$28.00',
|
714 |
+
'$65.00',
|
715 |
+
'$59.50',
|
716 |
+
),
|
717 |
+
),
|
718 |
+
),
|
719 |
+
'beta' => array(
|
720 |
+
'label' => 'Beta',
|
721 |
+
'styles' => array(
|
722 |
+
'title' => array(
|
723 |
+
'color' => '#393F4C',
|
724 |
+
'size' => 16,
|
725 |
+
),
|
726 |
+
'background' => array(
|
727 |
+
'color' => '#F0F2F4',
|
728 |
+
),
|
729 |
+
'price' => array(
|
730 |
+
'color' => '#4C5566',
|
731 |
+
'size' => 12,
|
732 |
+
),
|
733 |
+
'rating' => array(
|
734 |
+
'color' => '#F2D74A',
|
735 |
+
),
|
736 |
+
'meta' => array(
|
737 |
+
'price' => 'on',
|
738 |
+
'rating' => 'on',
|
739 |
+
'image' => 'on',
|
740 |
+
),
|
741 |
+
),
|
742 |
+
'list' => array(
|
743 |
+
'items' => array(
|
744 |
+
'Admin WPBeginner Black T-Shirt',
|
745 |
+
'Black WP Beginner logo T-Shirt',
|
746 |
+
'Technically Awesome Groovy White T-Shirt',
|
747 |
+
'Technically Awesome Code Comment Black T-Shirt',
|
748 |
+
),
|
749 |
+
'images' => array(
|
750 |
+
'theme-products-5.jpg',
|
751 |
+
'theme-products-7.jpg',
|
752 |
+
'theme-products-6.jpg',
|
753 |
+
'theme-products-8.jpg',
|
754 |
+
),
|
755 |
+
'prices' => array(
|
756 |
+
'$29.50',
|
757 |
+
'$28.00',
|
758 |
+
'$65.00',
|
759 |
+
'$59.50',
|
760 |
+
),
|
761 |
+
),
|
762 |
+
),
|
763 |
+
'charlie' => array(
|
764 |
+
'label' => 'Charlie',
|
765 |
+
'styles' => array(
|
766 |
+
'title' => array(
|
767 |
+
'color' => '#fff',
|
768 |
+
'size' => 16,
|
769 |
+
),
|
770 |
+
'rating' => array(
|
771 |
+
'color' => '#F2D74A',
|
772 |
+
),
|
773 |
+
'price' => array(
|
774 |
+
'color' => '#fff',
|
775 |
+
'size' => 12,
|
776 |
+
),
|
777 |
+
'meta' => array(
|
778 |
+
'price' => 'on',
|
779 |
+
'rating' => 'on',
|
780 |
+
),
|
781 |
+
),
|
782 |
+
'list' => array(
|
783 |
+
'items' => array(
|
784 |
+
'Admin WPBeginner Black T-Shirt',
|
785 |
+
'Black WP Beginner logo T-Shirt',
|
786 |
+
'Technically Awesome Groovy White T-Shirt',
|
787 |
+
'Technically Awesome Code Comment Black T-Shirt',
|
788 |
+
),
|
789 |
+
'images' => array(
|
790 |
+
'theme-products-5.jpg',
|
791 |
+
'theme-products-7.jpg',
|
792 |
+
'theme-products-6.jpg',
|
793 |
+
'theme-products-8.jpg',
|
794 |
+
),
|
795 |
+
'prices' => array(
|
796 |
+
'$29.50',
|
797 |
+
'$28.00',
|
798 |
+
'$65.00',
|
799 |
+
'$59.50',
|
800 |
+
),
|
801 |
+
),
|
802 |
+
'image' => true,
|
803 |
+
),
|
804 |
+
'delta' => array(
|
805 |
+
'label' => 'Delta',
|
806 |
+
'styles' => array(
|
807 |
+
'title' => array(
|
808 |
+
'color' => '#393f4c',
|
809 |
+
'size' => 14,
|
810 |
+
),
|
811 |
+
'rating' => array(
|
812 |
+
'color' => '#F2D74A',
|
813 |
+
),
|
814 |
+
'price' => array(
|
815 |
+
'color' => '#4C5566',
|
816 |
+
'size' => 12,
|
817 |
+
),
|
818 |
+
'meta' => array(
|
819 |
+
'price' => 'on',
|
820 |
+
'rating' => 'on',
|
821 |
+
'image' => 'on',
|
822 |
+
),
|
823 |
+
),
|
824 |
+
'list' => array(
|
825 |
+
'items' => array(
|
826 |
+
'Admin WPBeginner Black T-Shirt',
|
827 |
+
'Black WP Beginner logo T-Shirt',
|
828 |
+
'Technically Awesome Groovy White T-Shirt',
|
829 |
+
'Technically Awesome Code Comment Black T-Shirt',
|
830 |
+
),
|
831 |
+
'images' => array(
|
832 |
+
'theme-products-5.jpg',
|
833 |
+
'theme-products-7.jpg',
|
834 |
+
'theme-products-6.jpg',
|
835 |
+
'theme-products-8.jpg',
|
836 |
+
),
|
837 |
+
'prices' => array(
|
838 |
+
'$29.50',
|
839 |
+
'$28.00',
|
840 |
+
'$65.00',
|
841 |
+
'$59.50',
|
842 |
+
),
|
843 |
+
),
|
844 |
+
),
|
845 |
+
);
|
846 |
+
|
847 |
+
return $this->process_themes_styles( 'products', $themes );
|
848 |
+
}
|
849 |
+
|
850 |
+
}
|
includes/popular-posts/class-popular-posts.php
CHANGED
@@ -1,742 +1,742 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* This is the base class for the Popular Posts output functionality.
|
4 |
-
* Each actual Popular Posts option extends this class (inline, widget, products).
|
5 |
-
*
|
6 |
-
* @package ExactMetrics
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class ExactMetrics_Popular_Posts
|
11 |
-
*/
|
12 |
-
class ExactMetrics_Popular_Posts {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* The key prefix used to store the settings for the magic __get method.
|
16 |
-
*
|
17 |
-
* @var string
|
18 |
-
*/
|
19 |
-
protected $settings_key;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Name of the shortcode
|
23 |
-
*
|
24 |
-
* @var string
|
25 |
-
*/
|
26 |
-
protected $shortcode_key;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* The popular posts object type, by default inline, widget or products.
|
30 |
-
*
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
protected $type;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* An array of posts used in the query process.
|
37 |
-
*
|
38 |
-
* @var array
|
39 |
-
*/
|
40 |
-
public $posts = array();
|
41 |
-
|
42 |
-
/**
|
43 |
-
* An array of posts already displayed. Used to avoid duplicate posts on the same page.
|
44 |
-
*
|
45 |
-
* @var array
|
46 |
-
*/
|
47 |
-
public $shown_posts = array();
|
48 |
-
|
49 |
-
/**
|
50 |
-
* The inline styles string with theme specifics from the Vue settings.
|
51 |
-
* Each instance should append to this variable so we print styles for all the instances in the same place.
|
52 |
-
*
|
53 |
-
* @var string
|
54 |
-
*/
|
55 |
-
public static $inline_styles = '';
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Stores the option to use ajax to display the popular posts widgets on the frontend.
|
59 |
-
*
|
60 |
-
* @var string
|
61 |
-
*/
|
62 |
-
public $ajaxify;
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Stores the cache instance, specific to the plugin version.
|
66 |
-
*
|
67 |
-
* @var ExactMetrics_Popular_Posts_Cache
|
68 |
-
*/
|
69 |
-
public $cache;
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Holds the class object.
|
73 |
-
*
|
74 |
-
* @since 7.13.0
|
75 |
-
* @access public
|
76 |
-
* @var array
|
77 |
-
*/
|
78 |
-
public static $instances = array();
|
79 |
-
|
80 |
-
/**
|
81 |
-
* @var ExactMetrics_Popular_Posts_Themes
|
82 |
-
*/
|
83 |
-
protected $theme_props;
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Indicator that inline styles have been printed to avoid duplicates.
|
87 |
-
*
|
88 |
-
* @var bool
|
89 |
-
*/
|
90 |
-
private static $styles_printed = false;
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Number of posts to query from the db. Not all queried posts are used for display in the same widget.
|
94 |
-
*
|
95 |
-
* @var int
|
96 |
-
*/
|
97 |
-
public $posts_count = 15;
|
98 |
-
|
99 |
-
/**
|
100 |
-
* ExactMetrics_Popular_Posts constructor.
|
101 |
-
*/
|
102 |
-
public function __construct() {
|
103 |
-
|
104 |
-
$this->hooks();
|
105 |
-
$this->register_shortcode();
|
106 |
-
|
107 |
-
$this->ajaxify = exactmetrics_get_option( 'popular_posts_ajaxify', false );
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* Magic get for different types of popular posts.
|
112 |
-
*
|
113 |
-
* @param $name
|
114 |
-
*
|
115 |
-
* @return string|array|mixed
|
116 |
-
*/
|
117 |
-
public function __get( $name ) {
|
118 |
-
return exactmetrics_get_option( $this->settings_key . '_' . $name );
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Add hooks needed for the output.
|
123 |
-
*/
|
124 |
-
public function hooks() {
|
125 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'load_frontend_styles' ) );
|
126 |
-
|
127 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'maybe_load_ajaxify_script' ) );
|
128 |
-
|
129 |
-
$this->add_inline_styles();
|
130 |
-
}
|
131 |
-
|
132 |
-
/**
|
133 |
-
* Add inline styles for each widget type to a single variable for printing.
|
134 |
-
*/
|
135 |
-
protected function add_inline_styles() {
|
136 |
-
if ( 'no_styles' !== $this->styling ) {
|
137 |
-
self::$inline_styles .= $this->build_inline_styles();
|
138 |
-
}
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Should return object-specific inline styles.
|
143 |
-
*
|
144 |
-
* @return string
|
145 |
-
*/
|
146 |
-
public function build_inline_styles() {
|
147 |
-
return '';
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Register the shortcode for the specific class.
|
152 |
-
*/
|
153 |
-
public function register_shortcode() {
|
154 |
-
|
155 |
-
if ( ! empty( $this->shortcode_key ) ) {
|
156 |
-
add_shortcode( $this->shortcode_key, array( $this, 'render_shortcode' ) );
|
157 |
-
}
|
158 |
-
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Load the frontend styles if they are enabled.
|
163 |
-
*/
|
164 |
-
public function load_frontend_styles() {
|
165 |
-
|
166 |
-
// Only load our styles if enabled.
|
167 |
-
if ( apply_filters( 'exactmetrics_popular_posts_styles_output', 'no_styles' === $this->styling, $this ) ) {
|
168 |
-
return;
|
169 |
-
}
|
170 |
-
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
171 |
-
|
172 |
-
// Load Popular Posts styles.
|
173 |
-
wp_register_style( 'exactmetrics-popular-posts-style', plugins_url( 'assets/css/frontend' . $suffix . '.css', EXACTMETRICS_PLUGIN_FILE ), array(), exactmetrics_get_asset_version() );
|
174 |
-
|
175 |
-
$this->add_theme_specific_styles();
|
176 |
-
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* If the Ajaxify option is enabled, print needed scripts.
|
181 |
-
*/
|
182 |
-
public function maybe_load_ajaxify_script() {
|
183 |
-
if ( ! $this->ajaxify ) {
|
184 |
-
return;
|
185 |
-
}
|
186 |
-
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
187 |
-
|
188 |
-
wp_register_script( 'exactmetrics-popular-posts-js', plugins_url( 'assets/js/popular-posts' . $suffix . '.js', EXACTMETRICS_PLUGIN_FILE ), array(), exactmetrics_get_asset_version(), true );
|
189 |
-
|
190 |
-
wp_enqueue_script( 'exactmetrics-popular-posts-js' );
|
191 |
-
|
192 |
-
wp_localize_script( 'exactmetrics-popular-posts-js', 'exactmetrics_pp', array(
|
193 |
-
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
194 |
-
'post_id' => get_the_ID(),
|
195 |
-
) );
|
196 |
-
|
197 |
-
}
|
198 |
-
|
199 |
-
/**
|
200 |
-
* Add inline styles based on customizations from the vue panel.
|
201 |
-
*/
|
202 |
-
public function add_theme_specific_styles() {
|
203 |
-
|
204 |
-
if ( ! self::$styles_printed ) {
|
205 |
-
wp_add_inline_style( 'exactmetrics-popular-posts-style', $this->get_inline_styles() );
|
206 |
-
self::$styles_printed = true;
|
207 |
-
}
|
208 |
-
|
209 |
-
}
|
210 |
-
|
211 |
-
/**
|
212 |
-
* We have a single static variable for inline styles shared by all instances so we print just once.
|
213 |
-
*
|
214 |
-
* @return string
|
215 |
-
*/
|
216 |
-
public function get_inline_styles() {
|
217 |
-
return self::$inline_styles;
|
218 |
-
}
|
219 |
-
|
220 |
-
/**
|
221 |
-
* Rendering the shortcode.
|
222 |
-
*
|
223 |
-
* @return string
|
224 |
-
*/
|
225 |
-
public function render_shortcode( $args ) {
|
226 |
-
|
227 |
-
return apply_filters( 'exactmetrics_popular_posts_shortcode_output', $this->shortcode_output( $args ), $args, $this );
|
228 |
-
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Output of shortcode based on settings.
|
233 |
-
*
|
234 |
-
* @param array $args Arguments from shortcode/block.
|
235 |
-
*
|
236 |
-
* @return string
|
237 |
-
*/
|
238 |
-
public function shortcode_output( $args ) {
|
239 |
-
// Load frontend.css file when shortcode is available
|
240 |
-
wp_enqueue_style( 'exactmetrics-popular-posts-style' );
|
241 |
-
|
242 |
-
if ( $this->ajaxify ) {
|
243 |
-
return $this->get_ajax_json_data( $args );
|
244 |
-
} else {
|
245 |
-
return $this->get_rendered_html( $args );
|
246 |
-
}
|
247 |
-
}
|
248 |
-
|
249 |
-
/**
|
250 |
-
* Print inline JSON data that with settings that get processed using an AJAX call. Acts similar to printing out
|
251 |
-
* a shortcode with its settings but actually loading the output for that after the page was loaded, with AJAX.
|
252 |
-
*
|
253 |
-
* @param array $args Arguments from shortcode/block.
|
254 |
-
*
|
255 |
-
* @return string
|
256 |
-
*/
|
257 |
-
public function get_ajax_json_data( $args ) {
|
258 |
-
|
259 |
-
$args['type'] = $this->type;
|
260 |
-
|
261 |
-
$data = '<div><script type="application/json" class="exactmetrics-popular-posts-widget-json">';
|
262 |
-
$data .= wp_json_encode( $args );
|
263 |
-
$data .= '</script></div>';
|
264 |
-
|
265 |
-
return $data;
|
266 |
-
}
|
267 |
-
|
268 |
-
/**
|
269 |
-
* This is replaced with actual HTML output in child classes.
|
270 |
-
*
|
271 |
-
* @param array $args Arguments used to build specific html.
|
272 |
-
*
|
273 |
-
* @return string
|
274 |
-
*/
|
275 |
-
public function get_rendered_html( $args ) {
|
276 |
-
return '';
|
277 |
-
}
|
278 |
-
|
279 |
-
/**
|
280 |
-
* Get the cache instance for the set type.
|
281 |
-
*
|
282 |
-
* @return ExactMetrics_Popular_Posts_Cache
|
283 |
-
*/
|
284 |
-
public function get_cache() {
|
285 |
-
if ( ! isset( $this->cache ) ) {
|
286 |
-
$this->cache = new ExactMetrics_Popular_Posts_Cache( $this->type );
|
287 |
-
}
|
288 |
-
|
289 |
-
return $this->cache;
|
290 |
-
}
|
291 |
-
|
292 |
-
/**
|
293 |
-
* Use the query args to grab posts from the database.
|
294 |
-
*/
|
295 |
-
public function get_posts() {
|
296 |
-
|
297 |
-
$posts_args = $this->get_query_args();
|
298 |
-
|
299 |
-
$posts = $this->get_cache()->get_cached_posts( $posts_args );
|
300 |
-
|
301 |
-
if ( empty( $posts ) ) {
|
302 |
-
|
303 |
-
if ( isset( $posts_args['post__in'] ) && empty( $posts_args['post__in'] ) ) {
|
304 |
-
$this->posts = array();
|
305 |
-
|
306 |
-
return $this->posts;
|
307 |
-
}
|
308 |
-
$posts = get_posts( $posts_args );
|
309 |
-
|
310 |
-
$posts = $this->process_posts( $posts );
|
311 |
-
|
312 |
-
$this->get_cache()->save_posts_to_cache( $posts_args, $posts );
|
313 |
-
}
|
314 |
-
|
315 |
-
return apply_filters( 'exactmetrics_popular_posts_posts', $posts );
|
316 |
-
|
317 |
-
}
|
318 |
-
|
319 |
-
/**
|
320 |
-
* Go through posts from a WP Query and prepare them for output.
|
321 |
-
*
|
322 |
-
* @param array $posts Array of posts from WP Query or similar, also supports array of ids.
|
323 |
-
*
|
324 |
-
* @return array
|
325 |
-
*/
|
326 |
-
private function process_posts( $posts ) {
|
327 |
-
$processed_posts = array();
|
328 |
-
foreach ( $posts as $post ) {
|
329 |
-
if ( is_int( $post ) ) {
|
330 |
-
$post = get_post( $post );
|
331 |
-
}
|
332 |
-
$post_thumbnail = get_post_thumbnail_id( $post->ID );
|
333 |
-
$post_image = '';
|
334 |
-
$post_image_srcset = '';
|
335 |
-
if ( ! empty( $post_thumbnail ) ) {
|
336 |
-
$post_image = wp_get_attachment_image_src( $post_thumbnail, 'medium' );
|
337 |
-
if ( is_array( $post_image ) && ! empty( $post_image[0] ) ) {
|
338 |
-
$post_image = $post_image[0];
|
339 |
-
}
|
340 |
-
$post_image_srcset = wp_get_attachment_image_srcset( $post_thumbnail, 'medium' );
|
341 |
-
}
|
342 |
-
|
343 |
-
$author_data = get_userdata( $post->post_author );
|
344 |
-
|
345 |
-
$processed_posts[] = array(
|
346 |
-
'id' => $post->ID,
|
347 |
-
'title' => get_the_title( $post->ID ),
|
348 |
-
'link' => get_permalink( $post->ID ),
|
349 |
-
'image' => $post_image,
|
350 |
-
'srcset' => $post_image_srcset,
|
351 |
-
'image_id' => $post_thumbnail,
|
352 |
-
'author' => $post->post_author,
|
353 |
-
'author_name' => $author_data->display_name,
|
354 |
-
'date' => get_the_date( '', $post->ID ),
|
355 |
-
'comments' => get_comments_number( $post->ID ),
|
356 |
-
);
|
357 |
-
}
|
358 |
-
|
359 |
-
return $processed_posts;
|
360 |
-
}
|
361 |
-
|
362 |
-
/**
|
363 |
-
* Get the query args for grabbing the posts. This should probably get overwritten in child classes.
|
364 |
-
*
|
365 |
-
* @return mixed|void
|
366 |
-
*/
|
367 |
-
private function get_query_args() {
|
368 |
-
|
369 |
-
$args = array(
|
370 |
-
'numberposts' => $this->posts_count,
|
371 |
-
'ignore_sticky_posts' => true,
|
372 |
-
);
|
373 |
-
$args = wp_parse_args( $this->query_args(), $args );
|
374 |
-
|
375 |
-
return apply_filters( 'exactmetrics_popular_posts_query_args', $args );
|
376 |
-
}
|
377 |
-
|
378 |
-
/**
|
379 |
-
* Set the query args specific to this instance.
|
380 |
-
*
|
381 |
-
* @return array
|
382 |
-
*/
|
383 |
-
protected function query_args() {
|
384 |
-
|
385 |
-
if ( 'comments' === $this->sort ) {
|
386 |
-
return $this->get_query_args_comments();
|
387 |
-
} elseif ( 'sharedcount' === $this->sort ) {
|
388 |
-
return $this->get_query_args_sharedcount();
|
389 |
-
} elseif ( 'curated' === $this->sort ) {
|
390 |
-
return $this->get_query_args_curated();
|
391 |
-
}
|
392 |
-
|
393 |
-
}
|
394 |
-
|
395 |
-
|
396 |
-
/**
|
397 |
-
* Get the query args for ordering by comments.
|
398 |
-
*
|
399 |
-
* @return array
|
400 |
-
*/
|
401 |
-
protected function get_query_args_comments() {
|
402 |
-
|
403 |
-
$query_args = array(
|
404 |
-
'orderby' => 'comment_count',
|
405 |
-
'order' => 'DESC',
|
406 |
-
);
|
407 |
-
|
408 |
-
return $query_args;
|
409 |
-
}
|
410 |
-
|
411 |
-
/**
|
412 |
-
* Get the query args for ordering by sharedcount.
|
413 |
-
*
|
414 |
-
* @return array
|
415 |
-
*/
|
416 |
-
protected function get_query_args_sharedcount() {
|
417 |
-
|
418 |
-
$query_args = array(
|
419 |
-
'orderby' => 'meta_value_num',
|
420 |
-
'order' => 'DESC',
|
421 |
-
'meta_key' => '_exactmetrics_sharedcount_total',
|
422 |
-
);
|
423 |
-
|
424 |
-
return $query_args;
|
425 |
-
}
|
426 |
-
|
427 |
-
|
428 |
-
/**
|
429 |
-
* Build the query args for the curated option from the settings in the panel.
|
430 |
-
*
|
431 |
-
* @return array
|
432 |
-
*/
|
433 |
-
protected function get_query_args_curated() {
|
434 |
-
|
435 |
-
$posts = $this->curated;
|
436 |
-
$post_in = array();
|
437 |
-
|
438 |
-
if ( ! empty( $posts ) && is_array( $posts ) ) {
|
439 |
-
foreach ( $posts as $post ) {
|
440 |
-
if ( ! empty( $post['id'] ) ) {
|
441 |
-
$post_in[] = intval( $post['id'] );
|
442 |
-
}
|
443 |
-
}
|
444 |
-
}
|
445 |
-
|
446 |
-
$query_args = array(
|
447 |
-
'post__in' => $post_in,
|
448 |
-
);
|
449 |
-
|
450 |
-
return $query_args;
|
451 |
-
}
|
452 |
-
|
453 |
-
/**
|
454 |
-
* Load theme props for the specific instance.
|
455 |
-
*
|
456 |
-
* @param string $theme Theme key.
|
457 |
-
*
|
458 |
-
* @return ExactMetrics_Popular_Posts_Themes
|
459 |
-
*/
|
460 |
-
public function get_theme_props( $theme = '' ) {
|
461 |
-
|
462 |
-
if ( empty( $theme ) ) {
|
463 |
-
$theme = $this->theme;
|
464 |
-
}
|
465 |
-
$theme_props = new ExactMetrics_Popular_Posts_Themes( $this->type, $theme );
|
466 |
-
|
467 |
-
return $theme_props;
|
468 |
-
}
|
469 |
-
|
470 |
-
/**
|
471 |
-
* Marks a post as already displayed, by id.
|
472 |
-
*
|
473 |
-
* @param $id
|
474 |
-
*/
|
475 |
-
public function set_post_shown( $id ) {
|
476 |
-
if ( ! in_array( $id, $this->shown_posts, true ) ) {
|
477 |
-
$this->shown_posts[] = $id;
|
478 |
-
}
|
479 |
-
}
|
480 |
-
|
481 |
-
/**
|
482 |
-
* Returns an array of posts that were already displayed on the current page.
|
483 |
-
*
|
484 |
-
* @return array
|
485 |
-
*/
|
486 |
-
public function get_shown_posts() {
|
487 |
-
|
488 |
-
return $this->shown_posts;
|
489 |
-
|
490 |
-
}
|
491 |
-
|
492 |
-
/**
|
493 |
-
* Generic helper function to build style attributes for elements based on shortcode/block parameters.
|
494 |
-
*
|
495 |
-
* @param string $theme The theme for which we're building the style.
|
496 |
-
* @param string $object Object we're styling like title, label, background, etc.
|
497 |
-
* @param array $atts Attributes passed from shortcode/block.
|
498 |
-
* @param string $key The key of the style we're going to output.
|
499 |
-
*
|
500 |
-
* @return string
|
501 |
-
*/
|
502 |
-
public function get_element_style( $theme, $object, $atts, $key = '' ) {
|
503 |
-
|
504 |
-
if ( 'no_styles' === $this->styling ) {
|
505 |
-
// If no styles is selected don't output any styles.
|
506 |
-
return '';
|
507 |
-
}
|
508 |
-
|
509 |
-
if ( empty( $theme ) ) {
|
510 |
-
$theme = $this->theme;
|
511 |
-
}
|
512 |
-
|
513 |
-
// Find theme-specific available options and check if our attributes have those set.
|
514 |
-
$theme_styles = $this->get_theme_props( $theme )->get_theme();
|
515 |
-
$style_output = '';
|
516 |
-
$style_css = '';
|
517 |
-
|
518 |
-
if ( ! empty( $theme_styles['styles'] ) ) {
|
519 |
-
foreach ( $theme_styles['styles'] as $element => $options ) {
|
520 |
-
if ( $object !== $element ) {
|
521 |
-
continue;
|
522 |
-
}
|
523 |
-
foreach ( $options as $style_key => $value ) {
|
524 |
-
$atts_key = $element . '_' . $style_key;
|
525 |
-
|
526 |
-
if ( ! empty( $key ) && $key !== $style_key ) {
|
527 |
-
// Allow output for just a specific key.
|
528 |
-
continue;
|
529 |
-
}
|
530 |
-
|
531 |
-
if ( ! empty( $atts[ $atts_key ] ) ) {
|
532 |
-
if ( is_bool( $atts[ $atts_key ] ) || 'on' === $atts[ $atts_key ] ) {
|
533 |
-
continue;
|
534 |
-
}
|
535 |
-
if ( 'size' === $style_key ) {
|
536 |
-
$style_key = 'font-size';
|
537 |
-
$atts[ $atts_key ] .= 'px';
|
538 |
-
}
|
539 |
-
if ( 'background' === $style_key || 'background' === $element && 'color' === $style_key ) {
|
540 |
-
$style_key = 'background-color';
|
541 |
-
}
|
542 |
-
if ( 'border' === $element || 'border' === $style_key ) {
|
543 |
-
$style_key = 'border-color';
|
544 |
-
}
|
545 |
-
$style_css .= $style_key . ':' . $atts[ $atts_key ] . ';';
|
546 |
-
}
|
547 |
-
}
|
548 |
-
}
|
549 |
-
}
|
550 |
-
|
551 |
-
if ( ! empty( $style_css ) ) {
|
552 |
-
$style_output = 'style="' . $style_css . '"';
|
553 |
-
}
|
554 |
-
|
555 |
-
return $style_output;
|
556 |
-
|
557 |
-
}
|
558 |
-
|
559 |
-
/**
|
560 |
-
* Get the current instance based on the called class.
|
561 |
-
*
|
562 |
-
* @return mixed
|
563 |
-
*/
|
564 |
-
public static function get_instance() {
|
565 |
-
|
566 |
-
if ( ! function_exists( 'get_called_class' ) ) {
|
567 |
-
return false;
|
568 |
-
}
|
569 |
-
|
570 |
-
$class = get_called_class();
|
571 |
-
|
572 |
-
if ( ! isset( self::$instances[ $class ] ) ) {
|
573 |
-
self::$instances[ $class ] = new $class;
|
574 |
-
}
|
575 |
-
|
576 |
-
return self::$instances[ $class ];
|
577 |
-
|
578 |
-
}
|
579 |
-
|
580 |
-
/**
|
581 |
-
* Check if the post is excluded from loading the widget.
|
582 |
-
*
|
583 |
-
* @param null|WP_Post $post The post to check if it's excluded.
|
584 |
-
*
|
585 |
-
* @return bool
|
586 |
-
*/
|
587 |
-
public function is_post_excluded( $post = null ) {
|
588 |
-
if ( is_null( $post ) ) {
|
589 |
-
$post = get_post( get_the_ID() );
|
590 |
-
}
|
591 |
-
$excluded = false;
|
592 |
-
|
593 |
-
$posts_to_exclude = $this->exclude_posts;
|
594 |
-
if ( ! empty( $posts_to_exclude ) ) {
|
595 |
-
$post_ids = array();
|
596 |
-
foreach ( $posts_to_exclude as $exclude_post ) {
|
597 |
-
if ( ! empty( $exclude_post['id'] ) ) {
|
598 |
-
$post_ids[] = intval( $exclude_post['id'] );
|
599 |
-
}
|
600 |
-
}
|
601 |
-
|
602 |
-
if ( in_array( $post->ID, $post_ids, true ) ) {
|
603 |
-
$excluded = true;
|
604 |
-
}
|
605 |
-
}
|
606 |
-
|
607 |
-
return $excluded;
|
608 |
-
}
|
609 |
-
|
610 |
-
/**
|
611 |
-
* Build a wrapper class based on theme, instance and some settings.
|
612 |
-
*
|
613 |
-
* @param array $atts Attributes of the shortcode/instance to process for output.
|
614 |
-
*
|
615 |
-
* @return string
|
616 |
-
*/
|
617 |
-
public function get_wrapper_class( $atts ) {
|
618 |
-
$theme = $this->theme;
|
619 |
-
if ( ! empty( $atts['theme'] ) ) {
|
620 |
-
$theme = $atts['theme'];
|
621 |
-
}
|
622 |
-
$columns = ! empty( $atts['columns'] ) ? $atts['columns'] : $this->theme_columns;
|
623 |
-
$classes = array(
|
624 |
-
'exactmetrics-' . $this->type . '-popular-posts',
|
625 |
-
'exactmetrics-' . $this->type . '-popular-posts-' . $theme,
|
626 |
-
'no_styles' !== $this->styling ? 'exactmetrics-popular-posts-styled' : '',
|
627 |
-
);
|
628 |
-
|
629 |
-
if ( $columns ) {
|
630 |
-
$classes[] = 'exactmetrics-' . $this->type . '-popular-posts-columns-' . $columns;
|
631 |
-
}
|
632 |
-
|
633 |
-
if ( isset( $atts['className'] ) ) {
|
634 |
-
$classes[] = $atts['className'];
|
635 |
-
}
|
636 |
-
|
637 |
-
$classname = implode( ' ', $classes );
|
638 |
-
|
639 |
-
return $classname;
|
640 |
-
}
|
641 |
-
|
642 |
-
/**
|
643 |
-
* Check if the id is of the currently displayed post. Compatible with the Ajaxify functionality.
|
644 |
-
*
|
645 |
-
* @param $id
|
646 |
-
*
|
647 |
-
* @return bool
|
648 |
-
*/
|
649 |
-
public function is_current_post( $id ) {
|
650 |
-
|
651 |
-
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
652 |
-
$current_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : false;
|
653 |
-
|
654 |
-
return $id === $current_id;
|
655 |
-
}
|
656 |
-
|
657 |
-
// Only run this check for singular pages.
|
658 |
-
if ( ! is_singular() ) {
|
659 |
-
return false;
|
660 |
-
}
|
661 |
-
|
662 |
-
return get_the_ID() === absint( $id );
|
663 |
-
|
664 |
-
}
|
665 |
-
|
666 |
-
/**
|
667 |
-
* Helper function that checks if a post should be displayed on the current page.
|
668 |
-
*
|
669 |
-
* @param int $id
|
670 |
-
*
|
671 |
-
* @return bool
|
672 |
-
*/
|
673 |
-
public function should_display_post( $id ) {
|
674 |
-
$shown = $this->get_shown_posts();
|
675 |
-
if ( in_array( $id, $shown, true ) ) {
|
676 |
-
return false;
|
677 |
-
}
|
678 |
-
if ( $this->is_current_post( $id ) ) {
|
679 |
-
return false;
|
680 |
-
}
|
681 |
-
|
682 |
-
return true;
|
683 |
-
}
|
684 |
-
|
685 |
-
/**
|
686 |
-
* This function grabs the posts from the cache or a fresh query and runs them through a check if they should be
|
687 |
-
* displayed on the current page to avoid duplicates.
|
688 |
-
*
|
689 |
-
* @return array
|
690 |
-
*/
|
691 |
-
public function get_posts_to_display() {
|
692 |
-
$posts = $this->get_posts();
|
693 |
-
|
694 |
-
$returned_posts = array();
|
695 |
-
|
696 |
-
foreach ( $posts as $post ) {
|
697 |
-
if ( $this->should_display_post( $post['id'] ) ) {
|
698 |
-
$returned_posts[] = $post;
|
699 |
-
}
|
700 |
-
}
|
701 |
-
|
702 |
-
if ( apply_filters( 'exactmetrics_popular_posts_show_duplicates', true ) && count( $posts ) > 0 && count( $this->shown_posts ) > 0 && count( $returned_posts ) === 0 ) {
|
703 |
-
$this->shown_posts = array(); // Reset shown posts.
|
704 |
-
return $this->get_posts_to_display(); // Run the function to grab the same posts again.
|
705 |
-
}
|
706 |
-
|
707 |
-
return $returned_posts;
|
708 |
-
}
|
709 |
-
|
710 |
-
/**
|
711 |
-
* Check if the current instance has any posts available to display.
|
712 |
-
*
|
713 |
-
* @param array $posts Posts array to check if still available for display.
|
714 |
-
*
|
715 |
-
* @return bool
|
716 |
-
*/
|
717 |
-
public function has_posts_to_show( $posts ) {
|
718 |
-
|
719 |
-
foreach ( $posts as $post ) {
|
720 |
-
if ( $this->should_display_post( $post['id'] ) ) {
|
721 |
-
return true;
|
722 |
-
}
|
723 |
-
}
|
724 |
-
|
725 |
-
return false;
|
726 |
-
|
727 |
-
}
|
728 |
-
|
729 |
-
/**
|
730 |
-
* Only inline styles that were customized for the specific instance.
|
731 |
-
*
|
732 |
-
* @return array
|
733 |
-
*/
|
734 |
-
public function get_themes_styles_for_output() {
|
735 |
-
|
736 |
-
$stored_styles = $this->get_theme_props()->get_theme_stored_styles();
|
737 |
-
$themes = ! empty( $stored_styles[ $this->type ] ) && is_array( $stored_styles[ $this->type ] ) ? $stored_styles[ $this->type ] : array();
|
738 |
-
|
739 |
-
return $themes;
|
740 |
-
|
741 |
-
}
|
742 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This is the base class for the Popular Posts output functionality.
|
4 |
+
* Each actual Popular Posts option extends this class (inline, widget, products).
|
5 |
+
*
|
6 |
+
* @package ExactMetrics
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class ExactMetrics_Popular_Posts
|
11 |
+
*/
|
12 |
+
class ExactMetrics_Popular_Posts {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* The key prefix used to store the settings for the magic __get method.
|
16 |
+
*
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
protected $settings_key;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Name of the shortcode
|
23 |
+
*
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
protected $shortcode_key;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* The popular posts object type, by default inline, widget or products.
|
30 |
+
*
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
protected $type;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* An array of posts used in the query process.
|
37 |
+
*
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
public $posts = array();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* An array of posts already displayed. Used to avoid duplicate posts on the same page.
|
44 |
+
*
|
45 |
+
* @var array
|
46 |
+
*/
|
47 |
+
public $shown_posts = array();
|
48 |
+
|
49 |
+
/**
|
50 |
+
* The inline styles string with theme specifics from the Vue settings.
|
51 |
+
* Each instance should append to this variable so we print styles for all the instances in the same place.
|
52 |
+
*
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
public static $inline_styles = '';
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Stores the option to use ajax to display the popular posts widgets on the frontend.
|
59 |
+
*
|
60 |
+
* @var string
|
61 |
+
*/
|
62 |
+
public $ajaxify;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Stores the cache instance, specific to the plugin version.
|
66 |
+
*
|
67 |
+
* @var ExactMetrics_Popular_Posts_Cache
|
68 |
+
*/
|
69 |
+
public $cache;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Holds the class object.
|
73 |
+
*
|
74 |
+
* @since 7.13.0
|
75 |
+
* @access public
|
76 |
+
* @var array
|
77 |
+
*/
|
78 |
+
public static $instances = array();
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @var ExactMetrics_Popular_Posts_Themes
|
82 |
+
*/
|
83 |
+
protected $theme_props;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Indicator that inline styles have been printed to avoid duplicates.
|
87 |
+
*
|
88 |
+
* @var bool
|
89 |
+
*/
|
90 |
+
private static $styles_printed = false;
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Number of posts to query from the db. Not all queried posts are used for display in the same widget.
|
94 |
+
*
|
95 |
+
* @var int
|
96 |
+
*/
|
97 |
+
public $posts_count = 15;
|
98 |
+
|
99 |
+
/**
|
100 |
+
* ExactMetrics_Popular_Posts constructor.
|
101 |
+
*/
|
102 |
+
public function __construct() {
|
103 |
+
|
104 |
+
$this->hooks();
|
105 |
+
$this->register_shortcode();
|
106 |
+
|
107 |
+
$this->ajaxify = exactmetrics_get_option( 'popular_posts_ajaxify', false );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Magic get for different types of popular posts.
|
112 |
+
*
|
113 |
+
* @param $name
|
114 |
+
*
|
115 |
+
* @return string|array|mixed
|
116 |
+
*/
|
117 |
+
public function __get( $name ) {
|
118 |
+
return exactmetrics_get_option( $this->settings_key . '_' . $name );
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Add hooks needed for the output.
|
123 |
+
*/
|
124 |
+
public function hooks() {
|
125 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'load_frontend_styles' ) );
|
126 |
+
|
127 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'maybe_load_ajaxify_script' ) );
|
128 |
+
|
129 |
+
$this->add_inline_styles();
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Add inline styles for each widget type to a single variable for printing.
|
134 |
+
*/
|
135 |
+
protected function add_inline_styles() {
|
136 |
+
if ( 'no_styles' !== $this->styling ) {
|
137 |
+
self::$inline_styles .= $this->build_inline_styles();
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Should return object-specific inline styles.
|
143 |
+
*
|
144 |
+
* @return string
|
145 |
+
*/
|
146 |
+
public function build_inline_styles() {
|
147 |
+
return '';
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Register the shortcode for the specific class.
|
152 |
+
*/
|
153 |
+
public function register_shortcode() {
|
154 |
+
|
155 |
+
if ( ! empty( $this->shortcode_key ) ) {
|
156 |
+
add_shortcode( $this->shortcode_key, array( $this, 'render_shortcode' ) );
|
157 |
+
}
|
158 |
+
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Load the frontend styles if they are enabled.
|
163 |
+
*/
|
164 |
+
public function load_frontend_styles() {
|
165 |
+
|
166 |
+
// Only load our styles if enabled.
|
167 |
+
if ( apply_filters( 'exactmetrics_popular_posts_styles_output', 'no_styles' === $this->styling, $this ) ) {
|
168 |
+
return;
|
169 |
+
}
|
170 |
+
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
171 |
+
|
172 |
+
// Load Popular Posts styles.
|
173 |
+
wp_register_style( 'exactmetrics-popular-posts-style', plugins_url( 'assets/css/frontend' . $suffix . '.css', EXACTMETRICS_PLUGIN_FILE ), array(), exactmetrics_get_asset_version() );
|
174 |
+
|
175 |
+
$this->add_theme_specific_styles();
|
176 |
+
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* If the Ajaxify option is enabled, print needed scripts.
|
181 |
+
*/
|
182 |
+
public function maybe_load_ajaxify_script() {
|
183 |
+
if ( ! $this->ajaxify ) {
|
184 |
+
return;
|
185 |
+
}
|
186 |
+
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
187 |
+
|
188 |
+
wp_register_script( 'exactmetrics-popular-posts-js', plugins_url( 'assets/js/popular-posts' . $suffix . '.js', EXACTMETRICS_PLUGIN_FILE ), array(), exactmetrics_get_asset_version(), true );
|
189 |
+
|
190 |
+
wp_enqueue_script( 'exactmetrics-popular-posts-js' );
|
191 |
+
|
192 |
+
wp_localize_script( 'exactmetrics-popular-posts-js', 'exactmetrics_pp', array(
|
193 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
194 |
+
'post_id' => get_the_ID(),
|
195 |
+
) );
|
196 |
+
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Add inline styles based on customizations from the vue panel.
|
201 |
+
*/
|
202 |
+
public function add_theme_specific_styles() {
|
203 |
+
|
204 |
+
if ( ! self::$styles_printed ) {
|
205 |
+
wp_add_inline_style( 'exactmetrics-popular-posts-style', $this->get_inline_styles() );
|
206 |
+
self::$styles_printed = true;
|
207 |
+
}
|
208 |
+
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* We have a single static variable for inline styles shared by all instances so we print just once.
|
213 |
+
*
|
214 |
+
* @return string
|
215 |
+
*/
|
216 |
+
public function get_inline_styles() {
|
217 |
+
return self::$inline_styles;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Rendering the shortcode.
|
222 |
+
*
|
223 |
+
* @return string
|
224 |
+
*/
|
225 |
+
public function render_shortcode( $args ) {
|
226 |
+
|
227 |
+
return apply_filters( 'exactmetrics_popular_posts_shortcode_output', $this->shortcode_output( $args ), $args, $this );
|
228 |
+
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Output of shortcode based on settings.
|
233 |
+
*
|
234 |
+
* @param array $args Arguments from shortcode/block.
|
235 |
+
*
|
236 |
+
* @return string
|
237 |
+
*/
|
238 |
+
public function shortcode_output( $args ) {
|
239 |
+
// Load frontend.css file when shortcode is available
|
240 |
+
wp_enqueue_style( 'exactmetrics-popular-posts-style' );
|
241 |
+
|
242 |
+
if ( $this->ajaxify ) {
|
243 |
+
return $this->get_ajax_json_data( $args );
|
244 |
+
} else {
|
245 |
+
return $this->get_rendered_html( $args );
|
246 |
+
}
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Print inline JSON data that with settings that get processed using an AJAX call. Acts similar to printing out
|
251 |
+
* a shortcode with its settings but actually loading the output for that after the page was loaded, with AJAX.
|
252 |
+
*
|
253 |
+
* @param array $args Arguments from shortcode/block.
|
254 |
+
*
|
255 |
+
* @return string
|
256 |
+
*/
|
257 |
+
public function get_ajax_json_data( $args ) {
|
258 |
+
|
259 |
+
$args['type'] = $this->type;
|
260 |
+
|
261 |
+
$data = '<div><script type="application/json" class="exactmetrics-popular-posts-widget-json">';
|
262 |
+
$data .= wp_json_encode( $args );
|
263 |
+
$data .= '</script></div>';
|
264 |
+
|
265 |
+
return $data;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* This is replaced with actual HTML output in child classes.
|
270 |
+
*
|
271 |
+
* @param array $args Arguments used to build specific html.
|
272 |
+
*
|
273 |
+
* @return string
|
274 |
+
*/
|
275 |
+
public function get_rendered_html( $args ) {
|
276 |
+
return '';
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Get the cache instance for the set type.
|
281 |
+
*
|
282 |
+
* @return ExactMetrics_Popular_Posts_Cache
|
283 |
+
*/
|
284 |
+
public function get_cache() {
|
285 |
+
if ( ! isset( $this->cache ) ) {
|
286 |
+
$this->cache = new ExactMetrics_Popular_Posts_Cache( $this->type );
|
287 |
+
}
|
288 |
+
|
289 |
+
return $this->cache;
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Use the query args to grab posts from the database.
|
294 |
+
*/
|
295 |
+
public function get_posts() {
|
296 |
+
|
297 |
+
$posts_args = $this->get_query_args();
|
298 |
+
|
299 |
+
$posts = $this->get_cache()->get_cached_posts( $posts_args );
|
300 |
+
|
301 |
+
if ( empty( $posts ) ) {
|
302 |
+
|
303 |
+
if ( isset( $posts_args['post__in'] ) && empty( $posts_args['post__in'] ) ) {
|
304 |
+
$this->posts = array();
|
305 |
+
|
306 |
+
return $this->posts;
|
307 |
+
}
|
308 |
+
$posts = get_posts( $posts_args );
|
309 |
+
|
310 |
+
$posts = $this->process_posts( $posts );
|
311 |
+
|
312 |
+
$this->get_cache()->save_posts_to_cache( $posts_args, $posts );
|
313 |
+
}
|
314 |
+
|
315 |
+
return apply_filters( 'exactmetrics_popular_posts_posts', $posts );
|
316 |
+
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Go through posts from a WP Query and prepare them for output.
|
321 |
+
*
|
322 |
+
* @param array $posts Array of posts from WP Query or similar, also supports array of ids.
|
323 |
+
*
|
324 |
+
* @return array
|
325 |
+
*/
|
326 |
+
private function process_posts( $posts ) {
|
327 |
+
$processed_posts = array();
|
328 |
+
foreach ( $posts as $post ) {
|
329 |
+
if ( is_int( $post ) ) {
|
330 |
+
$post = get_post( $post );
|
331 |
+
}
|
332 |
+
$post_thumbnail = get_post_thumbnail_id( $post->ID );
|
333 |
+
$post_image = '';
|
334 |
+
$post_image_srcset = '';
|
335 |
+
if ( ! empty( $post_thumbnail ) ) {
|
336 |
+
$post_image = wp_get_attachment_image_src( $post_thumbnail, 'medium' );
|
337 |
+
if ( is_array( $post_image ) && ! empty( $post_image[0] ) ) {
|
338 |
+
$post_image = $post_image[0];
|
339 |
+
}
|
340 |
+
$post_image_srcset = wp_get_attachment_image_srcset( $post_thumbnail, 'medium' );
|
341 |
+
}
|
342 |
+
|
343 |
+
$author_data = get_userdata( $post->post_author );
|
344 |
+
|
345 |
+
$processed_posts[] = array(
|
346 |
+
'id' => $post->ID,
|
347 |
+
'title' => get_the_title( $post->ID ),
|
348 |
+
'link' => get_permalink( $post->ID ),
|
349 |
+
'image' => $post_image,
|
350 |
+
'srcset' => $post_image_srcset,
|
351 |
+
'image_id' => $post_thumbnail,
|
352 |
+
'author' => $post->post_author,
|
353 |
+
'author_name' => $author_data->display_name,
|
354 |
+
'date' => get_the_date( '', $post->ID ),
|
355 |
+
'comments' => get_comments_number( $post->ID ),
|
356 |
+
);
|
357 |
+
}
|
358 |
+
|
359 |
+
return $processed_posts;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Get the query args for grabbing the posts. This should probably get overwritten in child classes.
|
364 |
+
*
|
365 |
+
* @return mixed|void
|
366 |
+
*/
|
367 |
+
private function get_query_args() {
|
368 |
+
|
369 |
+
$args = array(
|
370 |
+
'numberposts' => $this->posts_count,
|
371 |
+
'ignore_sticky_posts' => true,
|
372 |
+
);
|
373 |
+
$args = wp_parse_args( $this->query_args(), $args );
|
374 |
+
|
375 |
+
return apply_filters( 'exactmetrics_popular_posts_query_args', $args );
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Set the query args specific to this instance.
|
380 |
+
*
|
381 |
+
* @return array
|
382 |
+
*/
|
383 |
+
protected function query_args() {
|
384 |
+
|
385 |
+
if ( 'comments' === $this->sort ) {
|
386 |
+
return $this->get_query_args_comments();
|
387 |
+
} elseif ( 'sharedcount' === $this->sort ) {
|
388 |
+
return $this->get_query_args_sharedcount();
|
389 |
+
} elseif ( 'curated' === $this->sort ) {
|
390 |
+
return $this->get_query_args_curated();
|
391 |
+
}
|
392 |
+
|
393 |
+
}
|
394 |
+
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Get the query args for ordering by comments.
|
398 |
+
*
|
399 |
+
* @return array
|
400 |
+
*/
|
401 |
+
protected function get_query_args_comments() {
|
402 |
+
|
403 |
+
$query_args = array(
|
404 |
+
'orderby' => 'comment_count',
|
405 |
+
'order' => 'DESC',
|
406 |
+
);
|
407 |
+
|
408 |
+
return $query_args;
|
409 |
+
}
|
410 |
+
|
411 |
+
/**
|
412 |
+
* Get the query args for ordering by sharedcount.
|
413 |
+
*
|
414 |
+
* @return array
|
415 |
+
*/
|
416 |
+
protected function get_query_args_sharedcount() {
|
417 |
+
|
418 |
+
$query_args = array(
|
419 |
+
'orderby' => 'meta_value_num',
|
420 |
+
'order' => 'DESC',
|
421 |
+
'meta_key' => '_exactmetrics_sharedcount_total',
|
422 |
+
);
|
423 |
+
|
424 |
+
return $query_args;
|
425 |
+
}
|
426 |
+
|
427 |
+
|
428 |
+
/**
|
429 |
+
* Build the query args for the curated option from the settings in the panel.
|
430 |
+
*
|
431 |
+
* @return array
|
432 |
+
*/
|
433 |
+
protected function get_query_args_curated() {
|
434 |
+
|
435 |
+
$posts = $this->curated;
|
436 |
+
$post_in = array();
|
437 |
+
|
438 |
+
if ( ! empty( $posts ) && is_array( $posts ) ) {
|
439 |
+
foreach ( $posts as $post ) {
|
440 |
+
if ( ! empty( $post['id'] ) ) {
|
441 |
+
$post_in[] = intval( $post['id'] );
|
442 |
+
}
|
443 |
+
}
|
444 |
+
}
|
445 |
+
|
446 |
+
$query_args = array(
|
447 |
+
'post__in' => $post_in,
|
448 |
+
);
|
449 |
+
|
450 |
+
return $query_args;
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Load theme props for the specific instance.
|
455 |
+
*
|
456 |
+
* @param string $theme Theme key.
|
457 |
+
*
|
458 |
+
* @return ExactMetrics_Popular_Posts_Themes
|
459 |
+
*/
|
460 |
+
public function get_theme_props( $theme = '' ) {
|
461 |
+
|
462 |
+
if ( empty( $theme ) ) {
|
463 |
+
$theme = $this->theme;
|
464 |
+
}
|
465 |
+
$theme_props = new ExactMetrics_Popular_Posts_Themes( $this->type, $theme );
|
466 |
+
|
467 |
+
return $theme_props;
|
468 |
+
}
|
469 |
+
|
470 |
+
/**
|
471 |
+
* Marks a post as already displayed, by id.
|
472 |
+
*
|
473 |
+
* @param $id
|
474 |
+
*/
|
475 |
+
public function set_post_shown( $id ) {
|
476 |
+
if ( ! in_array( $id, $this->shown_posts, true ) ) {
|
477 |
+
$this->shown_posts[] = $id;
|
478 |
+
}
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Returns an array of posts that were already displayed on the current page.
|
483 |
+
*
|
484 |
+
* @return array
|
485 |
+
*/
|
486 |
+
public function get_shown_posts() {
|
487 |
+
|
488 |
+
return $this->shown_posts;
|
489 |
+
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Generic helper function to build style attributes for elements based on shortcode/block parameters.
|
494 |
+
*
|
495 |
+
* @param string $theme The theme for which we're building the style.
|
496 |
+
* @param string $object Object we're styling like title, label, background, etc.
|
497 |
+
* @param array $atts Attributes passed from shortcode/block.
|
498 |
+
* @param string $key The key of the style we're going to output.
|
499 |
+
*
|
500 |
+
* @return string
|
501 |
+
*/
|
502 |
+
public function get_element_style( $theme, $object, $atts, $key = '' ) {
|
503 |
+
|
504 |
+
if ( 'no_styles' === $this->styling ) {
|
505 |
+
// If no styles is selected don't output any styles.
|
506 |
+
return '';
|
507 |
+
}
|
508 |
+
|
509 |
+
if ( empty( $theme ) ) {
|
510 |
+
$theme = $this->theme;
|
511 |
+
}
|
512 |
+
|
513 |
+
// Find theme-specific available options and check if our attributes have those set.
|
514 |
+
$theme_styles = $this->get_theme_props( $theme )->get_theme();
|
515 |
+
$style_output = '';
|
516 |
+
$style_css = '';
|
517 |
+
|
518 |
+
if ( ! empty( $theme_styles['styles'] ) ) {
|
519 |
+
foreach ( $theme_styles['styles'] as $element => $options ) {
|
520 |
+
if ( $object !== $element ) {
|
521 |
+
continue;
|
522 |
+
}
|
523 |
+
foreach ( $options as $style_key => $value ) {
|
524 |
+
$atts_key = $element . '_' . $style_key;
|
525 |
+
|
526 |
+
if ( ! empty( $key ) && $key !== $style_key ) {
|
527 |
+
// Allow output for just a specific key.
|
528 |
+
continue;
|
529 |
+
}
|
530 |
+
|
531 |
+
if ( ! empty( $atts[ $atts_key ] ) ) {
|
532 |
+
if ( is_bool( $atts[ $atts_key ] ) || 'on' === $atts[ $atts_key ] ) {
|
533 |
+
continue;
|
534 |
+
}
|
535 |
+
if ( 'size' === $style_key ) {
|
536 |
+
$style_key = 'font-size';
|
537 |
+
$atts[ $atts_key ] .= 'px';
|
538 |
+
}
|
539 |
+
if ( 'background' === $style_key || 'background' === $element && 'color' === $style_key ) {
|
540 |
+
$style_key = 'background-color';
|
541 |
+
}
|
542 |
+
if ( 'border' === $element || 'border' === $style_key ) {
|
543 |
+
$style_key = 'border-color';
|
544 |
+
}
|
545 |
+
$style_css .= $style_key . ':' . $atts[ $atts_key ] . ';';
|
546 |
+
}
|
547 |
+
}
|
548 |
+
}
|
549 |
+
}
|
550 |
+
|
551 |
+
if ( ! empty( $style_css ) ) {
|
552 |
+
$style_output = 'style="' . $style_css . '"';
|
553 |
+
}
|
554 |
+
|
555 |
+
return $style_output;
|
556 |
+
|
557 |
+
}
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Get the current instance based on the called class.
|
561 |
+
*
|
562 |
+
* @return mixed
|
563 |
+
*/
|
564 |
+
public static function get_instance() {
|
565 |
+
|
566 |
+
if ( ! function_exists( 'get_called_class' ) ) {
|
567 |
+
return false;
|
568 |
+
}
|
569 |
+
|
570 |
+
$class = get_called_class();
|
571 |
+
|
572 |
+
if ( ! isset( self::$instances[ $class ] ) ) {
|
573 |
+
self::$instances[ $class ] = new $class;
|
574 |
+
}
|
575 |
+
|
576 |
+
return self::$instances[ $class ];
|
577 |
+
|
578 |
+
}
|
579 |
+
|
580 |
+
/**
|
581 |
+
* Check if the post is excluded from loading the widget.
|
582 |
+
*
|
583 |
+
* @param null|WP_Post $post The post to check if it's excluded.
|
584 |
+
*
|
585 |
+
* @return bool
|
586 |
+
*/
|
587 |
+
public function is_post_excluded( $post = null ) {
|
588 |
+
if ( is_null( $post ) ) {
|
589 |
+
$post = get_post( get_the_ID() );
|
590 |
+
}
|
591 |
+
$excluded = false;
|
592 |
+
|
593 |
+
$posts_to_exclude = $this->exclude_posts;
|
594 |
+
if ( ! empty( $posts_to_exclude ) ) {
|
595 |
+
$post_ids = array();
|
596 |
+
foreach ( $posts_to_exclude as $exclude_post ) {
|
597 |
+
if ( ! empty( $exclude_post['id'] ) ) {
|
598 |
+
$post_ids[] = intval( $exclude_post['id'] );
|
599 |
+
}
|
600 |
+
}
|
601 |
+
|
602 |
+
if ( in_array( $post->ID, $post_ids, true ) ) {
|
603 |
+
$excluded = true;
|
604 |
+
}
|
605 |
+
}
|
606 |
+
|
607 |
+
return $excluded;
|
608 |
+
}
|
609 |
+
|
610 |
+
/**
|
611 |
+
* Build a wrapper class based on theme, instance and some settings.
|
612 |
+
*
|
613 |
+
* @param array $atts Attributes of the shortcode/instance to process for output.
|
614 |
+
*
|
615 |
+
* @return string
|
616 |
+
*/
|
617 |
+
public function get_wrapper_class( $atts ) {
|
618 |
+
$theme = $this->theme;
|
619 |
+
if ( ! empty( $atts['theme'] ) ) {
|
620 |
+
$theme = $atts['theme'];
|
621 |
+
}
|
622 |
+
$columns = ! empty( $atts['columns'] ) ? $atts['columns'] : $this->theme_columns;
|
623 |
+
$classes = array(
|
624 |
+
'exactmetrics-' . $this->type . '-popular-posts',
|
625 |
+
'exactmetrics-' . $this->type . '-popular-posts-' . $theme,
|
626 |
+
'no_styles' !== $this->styling ? 'exactmetrics-popular-posts-styled' : '',
|
627 |
+
);
|
628 |
+
|
629 |
+
if ( $columns ) {
|
630 |
+
$classes[] = 'exactmetrics-' . $this->type . '-popular-posts-columns-' . $columns;
|
631 |
+
}
|
632 |
+
|
633 |
+
if ( isset( $atts['className'] ) ) {
|
634 |
+
$classes[] = $atts['className'];
|
635 |
+
}
|
636 |
+
|
637 |
+
$classname = implode( ' ', $classes );
|
638 |
+
|
639 |
+
return $classname;
|
640 |
+
}
|
641 |
+
|
642 |
+
/**
|
643 |
+
* Check if the id is of the currently displayed post. Compatible with the Ajaxify functionality.
|
644 |
+
*
|
645 |
+
* @param $id
|
646 |
+
*
|
647 |
+
* @return bool
|
648 |
+
*/
|
649 |
+
public function is_current_post( $id ) {
|
650 |
+
|
651 |
+
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
652 |
+
$current_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : false;
|
653 |
+
|
654 |
+
return $id === $current_id;
|
655 |
+
}
|
656 |
+
|
657 |
+
// Only run this check for singular pages.
|
658 |
+
if ( ! is_singular() ) {
|
659 |
+
return false;
|
660 |
+
}
|
661 |
+
|
662 |
+
return get_the_ID() === absint( $id );
|
663 |
+
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* Helper function that checks if a post should be displayed on the current page.
|
668 |
+
*
|
669 |
+
* @param int $id
|
670 |
+
*
|
671 |
+
* @return bool
|
672 |
+
*/
|
673 |
+
public function should_display_post( $id ) {
|
674 |
+
$shown = $this->get_shown_posts();
|
675 |
+
if ( in_array( $id, $shown, true ) ) {
|
676 |
+
return false;
|
677 |
+
}
|
678 |
+
if ( $this->is_current_post( $id ) ) {
|
679 |
+
return false;
|
680 |
+
}
|
681 |
+
|
682 |
+
return true;
|
683 |
+
}
|
684 |
+
|
685 |
+
/**
|
686 |
+
* This function grabs the posts from the cache or a fresh query and runs them through a check if they should be
|
687 |
+
* displayed on the current page to avoid duplicates.
|
688 |
+
*
|
689 |
+
* @return array
|
690 |
+
*/
|
691 |
+
public function get_posts_to_display() {
|
692 |
+
$posts = $this->get_posts();
|
693 |
+
|
694 |
+
$returned_posts = array();
|
695 |
+
|
696 |
+
foreach ( $posts as $post ) {
|
697 |
+
if ( $this->should_display_post( $post['id'] ) ) {
|
698 |
+
$returned_posts[] = $post;
|
699 |
+
}
|
700 |
+
}
|
701 |
+
|
702 |
+
if ( apply_filters( 'exactmetrics_popular_posts_show_duplicates', true ) && count( $posts ) > 0 && count( $this->shown_posts ) > 0 && count( $returned_posts ) === 0 ) {
|
703 |
+
$this->shown_posts = array(); // Reset shown posts.
|
704 |
+
return $this->get_posts_to_display(); // Run the function to grab the same posts again.
|
705 |
+
}
|
706 |
+
|
707 |
+
return $returned_posts;
|
708 |
+
}
|
709 |
+
|
710 |
+
/**
|
711 |
+
* Check if the current instance has any posts available to display.
|
712 |
+
*
|
713 |
+
* @param array $posts Posts array to check if still available for display.
|
714 |
+
*
|
715 |
+
* @return bool
|
716 |
+
*/
|
717 |
+
public function has_posts_to_show( $posts ) {
|
718 |
+
|
719 |
+
foreach ( $posts as $post ) {
|
720 |
+
if ( $this->should_display_post( $post['id'] ) ) {
|
721 |
+
return true;
|
722 |
+
}
|
723 |
+
}
|
724 |
+
|
725 |
+
return false;
|
726 |
+
|
727 |
+
}
|
728 |
+
|
729 |
+
/**
|
730 |
+
* Only inline styles that were customized for the specific instance.
|
731 |
+
*
|
732 |
+
* @return array
|
733 |
+
*/
|
734 |
+
public function get_themes_styles_for_output() {
|
735 |
+
|
736 |
+
$stored_styles = $this->get_theme_props()->get_theme_stored_styles();
|
737 |
+
$themes = ! empty( $stored_styles[ $this->type ] ) && is_array( $stored_styles[ $this->type ] ) ? $stored_styles[ $this->type ] : array();
|
738 |
+
|
739 |
+
return $themes;
|
740 |
+
|
741 |
+
}
|
742 |
+
}
|
lite/includes/gutenberg/blocks/blocks.php
CHANGED
@@ -1,162 +1,162 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Gutenberg Blocks registration class.
|
4 |
-
*
|
5 |
-
* @since 7.13.9
|
6 |
-
*
|
7 |
-
* @package ExactMetrics
|
8 |
-
*/
|
9 |
-
|
10 |
-
// Exit if accessed directly.
|
11 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
-
exit;
|
13 |
-
}
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Gutenberg Blocks registration class.
|
17 |
-
*
|
18 |
-
* @since 7.13.0
|
19 |
-
*/
|
20 |
-
class ExactMetrics_Blocks {
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Holds the class object.
|
24 |
-
*
|
25 |
-
* @since 7.13.0
|
26 |
-
*
|
27 |
-
* @var object
|
28 |
-
*/
|
29 |
-
public static $instance;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Path to the file.
|
33 |
-
*
|
34 |
-
* @since 7.13.0
|
35 |
-
*
|
36 |
-
* @var string
|
37 |
-
*/
|
38 |
-
public $file = __FILE__;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Holds the base class object.
|
42 |
-
*
|
43 |
-
* @since 7.13.0
|
44 |
-
*
|
45 |
-
* @var object
|
46 |
-
*/
|
47 |
-
public $base;
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Primary class constructor.
|
51 |
-
*
|
52 |
-
* @since 7.13.0
|
53 |
-
*/
|
54 |
-
public function __construct() {
|
55 |
-
|
56 |
-
if ( function_exists( 'register_block_type' ) ) {
|
57 |
-
|
58 |
-
// Set our object.
|
59 |
-
$this->set();
|
60 |
-
$this->register_blocks();
|
61 |
-
}
|
62 |
-
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Sets our object instance and base class instance.
|
67 |
-
*
|
68 |
-
* @since 7.13.0
|
69 |
-
*/
|
70 |
-
public function set() {
|
71 |
-
self::$instance = $this;
|
72 |
-
}
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Register ExactMetrics Gutenberg blocks on the backend.
|
76 |
-
*
|
77 |
-
* @since 7.13.0
|
78 |
-
*/
|
79 |
-
public function register_blocks() {
|
80 |
-
register_block_type(
|
81 |
-
'exactmetrics/popular-posts-inline',
|
82 |
-
array(
|
83 |
-
'attributes' => array(
|
84 |
-
'slug' => array(
|
85 |
-
'type' => 'string',
|
86 |
-
),
|
87 |
-
'followrules' => array(
|
88 |
-
'type' => 'boolean',
|
89 |
-
),
|
90 |
-
),
|
91 |
-
'render_callback' => array( $this, 'popular_posts_inline_output' ),
|
92 |
-
)
|
93 |
-
);
|
94 |
-
register_block_type(
|
95 |
-
'exactmetrics/popular-posts-widget',
|
96 |
-
array(
|
97 |
-
'attributes' => array(
|
98 |
-
'slug' => array(
|
99 |
-
'type' => 'string',
|
100 |
-
),
|
101 |
-
'followrules' => array(
|
102 |
-
'type' => 'boolean',
|
103 |
-
),
|
104 |
-
),
|
105 |
-
'render_callback' => array( $this, 'popular_posts_widget_output' ),
|
106 |
-
)
|
107 |
-
);
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* Get form HTML to display in a ExactMetrics Gutenberg block.
|
112 |
-
*
|
113 |
-
* @param array $atts Attributes passed by ExactMetrics Gutenberg block.
|
114 |
-
*
|
115 |
-
* @return string
|
116 |
-
* @since 7.13.0
|
117 |
-
*
|
118 |
-
*/
|
119 |
-
public function popular_posts_inline_output( $atts ) {
|
120 |
-
|
121 |
-
$output = ExactMetrics_Popular_Posts_Inline()->shortcode_output( $atts );
|
122 |
-
|
123 |
-
return $output;
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Get form HTML to display in a ExactMetrics Gutenberg block.
|
128 |
-
*
|
129 |
-
* @param array $atts Attributes passed by ExactMetrics Gutenberg block.
|
130 |
-
*
|
131 |
-
* @return string
|
132 |
-
* @since 7.13.0
|
133 |
-
*/
|
134 |
-
public function popular_posts_widget_output( $atts ) {
|
135 |
-
|
136 |
-
$atts = $this->add_default_values( $atts );
|
137 |
-
$output = ExactMetrics_Popular_Posts_Widget()->shortcode_output( $atts );
|
138 |
-
|
139 |
-
return $output;
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* This ensures that what is displayed as default in the Gutenberg block is reflected in the output.
|
144 |
-
*
|
145 |
-
* @param array $atts The attributes from Gutenberg.
|
146 |
-
*
|
147 |
-
* @return array
|
148 |
-
*/
|
149 |
-
private function add_default_values( $atts ) {
|
150 |
-
|
151 |
-
$default_values = array(
|
152 |
-
'columns' => 1,
|
153 |
-
'widget_title' => false,
|
154 |
-
);
|
155 |
-
|
156 |
-
return wp_parse_args( $atts, $default_values );
|
157 |
-
|
158 |
-
}
|
159 |
-
|
160 |
-
}
|
161 |
-
|
162 |
-
new ExactMetrics_Blocks();
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Gutenberg Blocks registration class.
|
4 |
+
*
|
5 |
+
* @since 7.13.9
|
6 |
+
*
|
7 |
+
* @package ExactMetrics
|
8 |
+
*/
|
9 |
+
|
10 |
+
// Exit if accessed directly.
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Gutenberg Blocks registration class.
|
17 |
+
*
|
18 |
+
* @since 7.13.0
|
19 |
+
*/
|
20 |
+
class ExactMetrics_Blocks {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Holds the class object.
|
24 |
+
*
|
25 |
+
* @since 7.13.0
|
26 |
+
*
|
27 |
+
* @var object
|
28 |
+
*/
|
29 |
+
public static $instance;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Path to the file.
|
33 |
+
*
|
34 |
+
* @since 7.13.0
|
35 |
+
*
|
36 |
+
* @var string
|
37 |
+
*/
|
38 |
+
public $file = __FILE__;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Holds the base class object.
|
42 |
+
*
|
43 |
+
* @since 7.13.0
|
44 |
+
*
|
45 |
+
* @var object
|
46 |
+
*/
|
47 |
+
public $base;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Primary class constructor.
|
51 |
+
*
|
52 |
+
* @since 7.13.0
|
53 |
+
*/
|
54 |
+
public function __construct() {
|
55 |
+
|
56 |
+
if ( function_exists( 'register_block_type' ) ) {
|
57 |
+
|
58 |
+
// Set our object.
|
59 |
+
$this->set();
|
60 |
+
$this->register_blocks();
|
61 |
+
}
|
62 |
+
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Sets our object instance and base class instance.
|
67 |
+
*
|
68 |
+
* @since 7.13.0
|
69 |
+
*/
|
70 |
+
public function set() {
|
71 |
+
self::$instance = $this;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Register ExactMetrics Gutenberg blocks on the backend.
|
76 |
+
*
|
77 |
+
* @since 7.13.0
|
78 |
+
*/
|
79 |
+
public function register_blocks() {
|
80 |
+
register_block_type(
|
81 |
+
'exactmetrics/popular-posts-inline',
|
82 |
+
array(
|
83 |
+
'attributes' => array(
|
84 |
+
'slug' => array(
|
85 |
+
'type' => 'string',
|
86 |
+
),
|
87 |
+
'followrules' => array(
|
88 |
+
'type' => 'boolean',
|
89 |
+
),
|
90 |
+
),
|
91 |
+
'render_callback' => array( $this, 'popular_posts_inline_output' ),
|
92 |
+
)
|
93 |
+
);
|
94 |
+
register_block_type(
|
95 |
+
'exactmetrics/popular-posts-widget',
|
96 |
+
array(
|
97 |
+
'attributes' => array(
|
98 |
+
'slug' => array(
|
99 |
+
'type' => 'string',
|
100 |
+
),
|
101 |
+
'followrules' => array(
|
102 |
+
'type' => 'boolean',
|
103 |
+
),
|
104 |
+
),
|
105 |
+
'render_callback' => array( $this, 'popular_posts_widget_output' ),
|
106 |
+
)
|
107 |
+
);
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get form HTML to display in a ExactMetrics Gutenberg block.
|
112 |
+
*
|
113 |
+
* @param array $atts Attributes passed by ExactMetrics Gutenberg block.
|
114 |
+
*
|
115 |
+
* @return string
|
116 |
+
* @since 7.13.0
|
117 |
+
*
|
118 |
+
*/
|
119 |
+
public function popular_posts_inline_output( $atts ) {
|
120 |
+
|
121 |
+
$output = ExactMetrics_Popular_Posts_Inline()->shortcode_output( $atts );
|
122 |
+
|
123 |
+
return $output;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get form HTML to display in a ExactMetrics Gutenberg block.
|
128 |
+
*
|
129 |
+
* @param array $atts Attributes passed by ExactMetrics Gutenberg block.
|
130 |
+
*
|
131 |
+
* @return string
|
132 |
+
* @since 7.13.0
|
133 |
+
*/
|
134 |
+
public function popular_posts_widget_output( $atts ) {
|
135 |
+
|
136 |
+
$atts = $this->add_default_values( $atts );
|
137 |
+
$output = ExactMetrics_Popular_Posts_Widget()->shortcode_output( $atts );
|
138 |
+
|
139 |
+
return $output;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* This ensures that what is displayed as default in the Gutenberg block is reflected in the output.
|
144 |
+
*
|
145 |
+
* @param array $atts The attributes from Gutenberg.
|
146 |
+
*
|
147 |
+
* @return array
|
148 |
+
*/
|
149 |
+
private function add_default_values( $atts ) {
|
150 |
+
|
151 |
+
$default_values = array(
|
152 |
+
'columns' => 1,
|
153 |
+
'widget_title' => false,
|
154 |
+
);
|
155 |
+
|
156 |
+
return wp_parse_args( $atts, $default_values );
|
157 |
+
|
158 |
+
}
|
159 |
+
|
160 |
+
}
|
161 |
+
|
162 |
+
new ExactMetrics_Blocks();
|
lite/includes/gutenberg/frontend.php
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
require_once EXACTMETRICS_PLUGIN_DIR . 'lite/includes/gutenberg/blocks/blocks.php';
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once EXACTMETRICS_PLUGIN_DIR . 'lite/includes/gutenberg/blocks/blocks.php';
|
lite/includes/popular-posts/class-popular-posts-ajax.php
CHANGED
@@ -1,259 +1,259 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Used to handle ajax requests specific to popular posts.
|
4 |
-
*
|
5 |
-
* @package ExactMetrics
|
6 |
-
*/
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class ExactMetrics_Popular_Posts_Ajax
|
10 |
-
*/
|
11 |
-
class ExactMetrics_Popular_Posts_Ajax {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* ExactMetrics_Popular_Posts_Ajax constructor.
|
15 |
-
*/
|
16 |
-
public function __construct() {
|
17 |
-
|
18 |
-
add_action( 'rest_api_init', array( $this, 'register_api_endpoints' ) );
|
19 |
-
|
20 |
-
add_action( 'wp_ajax_exactmetrics_popular_posts_empty_cache', array( $this, 'empty_cache' ) );
|
21 |
-
|
22 |
-
add_action( 'wp_ajax_exactmetrics_popular_posts_get_widget_output', array( $this, 'get_ajax_output' ) );
|
23 |
-
add_action( 'wp_ajax_nopriv_exactmetrics_popular_posts_get_widget_output', array(
|
24 |
-
$this,
|
25 |
-
'get_ajax_output'
|
26 |
-
) );
|
27 |
-
|
28 |
-
add_action( 'wp_ajax_exactmetrics_get_popular_posts_themes', array( $this, 'ajax_get_themes' ) );
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Register the wp-json API endpoints for the Gutenberg blocks.
|
33 |
-
*/
|
34 |
-
public function register_api_endpoints() {
|
35 |
-
|
36 |
-
register_rest_route( 'exactmetrics/v1', '/popular-posts/themes/(?P<type>[a-zA-Z0-9-]+)', array(
|
37 |
-
'methods' => 'GET',
|
38 |
-
'callback' => array( $this, 'get_gutenberg_themes' ),
|
39 |
-
'permission_callback' => function () {
|
40 |
-
return current_user_can( 'edit_posts' );
|
41 |
-
},
|
42 |
-
'args' => array(
|
43 |
-
'type' => array(),
|
44 |
-
),
|
45 |
-
) );
|
46 |
-
|
47 |
-
register_rest_route( 'exactmetrics/v1', '/terms/(?P<slug>[a-zA-Z0-9-_]+)', array(
|
48 |
-
'methods' => 'GET',
|
49 |
-
'callback' => array( $this, 'get_taxonomy_terms' ),
|
50 |
-
'permission_callback' => function () {
|
51 |
-
return current_user_can( 'edit_posts' );
|
52 |
-
},
|
53 |
-
'args' => array(
|
54 |
-
'slug' => array(),
|
55 |
-
),
|
56 |
-
) );
|
57 |
-
|
58 |
-
register_rest_route( 'exactmetrics/v1', '/taxonomy/(?P<slug>[a-zA-Z0-9-_]+)', array(
|
59 |
-
'methods' => 'GET',
|
60 |
-
'callback' => array( $this, 'get_taxonomy' ),
|
61 |
-
'permission_callback' => function () {
|
62 |
-
return current_user_can( 'edit_posts' );
|
63 |
-
},
|
64 |
-
'args' => array(
|
65 |
-
'slug' => array(),
|
66 |
-
),
|
67 |
-
) );
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Get the themes for Gutenberg (use the specific nonce).
|
72 |
-
*/
|
73 |
-
public function get_gutenberg_themes( $data ) {
|
74 |
-
|
75 |
-
$type = ! empty( $data['type'] ) ? $data['type'] : 'inline';
|
76 |
-
|
77 |
-
return $this->get_themes_by_type( $type );
|
78 |
-
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Get the themes for a specific type using ajax.
|
83 |
-
*/
|
84 |
-
public function ajax_get_themes() {
|
85 |
-
|
86 |
-
check_ajax_referer( 'mi-admin-nonce', 'nonce' );
|
87 |
-
|
88 |
-
$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : 'inline';
|
89 |
-
|
90 |
-
wp_send_json_success( $this->get_themes_by_type( $type, false ) );
|
91 |
-
|
92 |
-
}
|
93 |
-
|
94 |
-
/**
|
95 |
-
* Helper to get themes by type.
|
96 |
-
*
|
97 |
-
* @param string $type The widget type: inline/widget/products.
|
98 |
-
* @param bool $styled Whether to style the selected theme or not.
|
99 |
-
*
|
100 |
-
* @return array
|
101 |
-
*/
|
102 |
-
public function get_themes_by_type( $type, $styled = true ) {
|
103 |
-
$theme = '';
|
104 |
-
|
105 |
-
if ( $styled ) {
|
106 |
-
if ( 'inline' === $type ) {
|
107 |
-
$theme = ExactMetrics_Popular_Posts_Inline()->theme;
|
108 |
-
}
|
109 |
-
|
110 |
-
if ( 'widget' === $type ) {
|
111 |
-
$theme = ExactMetrics_Popular_Posts_Widget()->theme;
|
112 |
-
}
|
113 |
-
}
|
114 |
-
$themes = $this->get_themes( $type, $theme );
|
115 |
-
$themes_array = $themes->themes;
|
116 |
-
|
117 |
-
if ( isset( $themes_array[ $theme ] ) && $styled ) {
|
118 |
-
$themes_array[ $theme ] = $themes->get_theme();
|
119 |
-
}
|
120 |
-
|
121 |
-
$response = array(
|
122 |
-
'themes' => $themes_array,
|
123 |
-
'selected' => $theme,
|
124 |
-
);
|
125 |
-
|
126 |
-
return $response;
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* Get themes by type.
|
131 |
-
*
|
132 |
-
* @param string $type The widget type: inline/widget/products.
|
133 |
-
* @param string $theme The selected theme.
|
134 |
-
*
|
135 |
-
* @return ExactMetrics_Popular_Posts_Themes
|
136 |
-
*/
|
137 |
-
public function get_themes( $type, $theme ) {
|
138 |
-
|
139 |
-
$themes_object = new ExactMetrics_Popular_Posts_Themes( $type, $theme );
|
140 |
-
|
141 |
-
return $themes_object;
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* Get a specific theme details.
|
146 |
-
*
|
147 |
-
* @param string $type The widget type: inline/widget/products.
|
148 |
-
* @param string $theme The selected theme.
|
149 |
-
*
|
150 |
-
* @return array|mixed
|
151 |
-
*/
|
152 |
-
public function get_theme_details( $type, $theme ) {
|
153 |
-
|
154 |
-
$themes = new ExactMetrics_Popular_Posts_Themes( $type, $theme );
|
155 |
-
|
156 |
-
return $themes->get_theme();
|
157 |
-
|
158 |
-
}
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Handler for loading taxonomy terms using a custom endpoint.
|
162 |
-
*
|
163 |
-
* @param array $data Data passed from the request.
|
164 |
-
*
|
165 |
-
* @return array
|
166 |
-
*/
|
167 |
-
public function get_taxonomy_terms( $data ) {
|
168 |
-
|
169 |
-
$slug = ! empty( $data['slug'] ) ? $data['slug'] : 'category';
|
170 |
-
|
171 |
-
$terms = get_terms( array(
|
172 |
-
'taxonomy' => $slug,
|
173 |
-
) );
|
174 |
-
|
175 |
-
$return = array();
|
176 |
-
|
177 |
-
if ( ! is_wp_error( $terms ) ) {
|
178 |
-
foreach ( $terms as $term ) {
|
179 |
-
$return[] = array(
|
180 |
-
'id' => $term->term_id,
|
181 |
-
'name' => $term->name,
|
182 |
-
'parent' => $term->parent,
|
183 |
-
);
|
184 |
-
}
|
185 |
-
}
|
186 |
-
|
187 |
-
return $return;
|
188 |
-
|
189 |
-
}
|
190 |
-
|
191 |
-
/**
|
192 |
-
* Get details for a taxonomy so we can use it in the Gutenberg block.
|
193 |
-
*
|
194 |
-
* @param array $data Data passed from the request.
|
195 |
-
*
|
196 |
-
* @return false|WP_Taxonomy
|
197 |
-
*/
|
198 |
-
public function get_taxonomy( $data ) {
|
199 |
-
|
200 |
-
$slug = ! empty( $data['slug'] ) ? $data['slug'] : 'category';
|
201 |
-
|
202 |
-
return get_taxonomy( $slug );
|
203 |
-
|
204 |
-
}
|
205 |
-
|
206 |
-
/**
|
207 |
-
* Ajax handler to empty the Popular Posts cache for all instances.
|
208 |
-
*/
|
209 |
-
public function empty_cache() {
|
210 |
-
|
211 |
-
check_ajax_referer( 'mi-admin-nonce', 'nonce' );
|
212 |
-
|
213 |
-
if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
|
214 |
-
return;
|
215 |
-
}
|
216 |
-
|
217 |
-
$types = array(
|
218 |
-
'inline',
|
219 |
-
'widget',
|
220 |
-
'products',
|
221 |
-
);
|
222 |
-
|
223 |
-
foreach ( $types as $type ) {
|
224 |
-
delete_option( 'exactmetrics_popular_posts_cache_' . $type );
|
225 |
-
}
|
226 |
-
|
227 |
-
wp_send_json_success();
|
228 |
-
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Ajax handler to get the output for Popular Posts widgets from the JSON data on the frontend.
|
233 |
-
*/
|
234 |
-
public function get_ajax_output() {
|
235 |
-
|
236 |
-
if ( empty( $_POST['data'] ) || ! is_array( $_POST['data'] ) ) {
|
237 |
-
return;
|
238 |
-
}
|
239 |
-
|
240 |
-
$html = array();
|
241 |
-
$widgets_args = $_POST['data'];
|
242 |
-
|
243 |
-
foreach ( $widgets_args as $args ) {
|
244 |
-
$args = json_decode( sanitize_text_field( wp_unslash( $args ) ), true );
|
245 |
-
if ( ! empty( $args['type'] ) ) {
|
246 |
-
$type = ucfirst( $args['type'] );
|
247 |
-
$widget_function = function_exists( 'ExactMetrics_Popular_Posts_' . $type ) ? call_user_func( 'ExactMetrics_Popular_Posts_' . $type ) : false;
|
248 |
-
if ( $widget_function ) {
|
249 |
-
$html[] = $widget_function->get_rendered_html( $args );
|
250 |
-
}
|
251 |
-
}
|
252 |
-
}
|
253 |
-
|
254 |
-
wp_send_json( $html );
|
255 |
-
}
|
256 |
-
|
257 |
-
}
|
258 |
-
|
259 |
-
new ExactMetrics_Popular_Posts_Ajax();
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Used to handle ajax requests specific to popular posts.
|
4 |
+
*
|
5 |
+
* @package ExactMetrics
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class ExactMetrics_Popular_Posts_Ajax
|
10 |
+
*/
|
11 |
+
class ExactMetrics_Popular_Posts_Ajax {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* ExactMetrics_Popular_Posts_Ajax constructor.
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
|
18 |
+
add_action( 'rest_api_init', array( $this, 'register_api_endpoints' ) );
|
19 |
+
|
20 |
+
add_action( 'wp_ajax_exactmetrics_popular_posts_empty_cache', array( $this, 'empty_cache' ) );
|
21 |
+
|
22 |
+
add_action( 'wp_ajax_exactmetrics_popular_posts_get_widget_output', array( $this, 'get_ajax_output' ) );
|
23 |
+
add_action( 'wp_ajax_nopriv_exactmetrics_popular_posts_get_widget_output', array(
|
24 |
+
$this,
|
25 |
+
'get_ajax_output'
|
26 |
+
) );
|
27 |
+
|
28 |
+
add_action( 'wp_ajax_exactmetrics_get_popular_posts_themes', array( $this, 'ajax_get_themes' ) );
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Register the wp-json API endpoints for the Gutenberg blocks.
|
33 |
+
*/
|
34 |
+
public function register_api_endpoints() {
|
35 |
+
|
36 |
+
register_rest_route( 'exactmetrics/v1', '/popular-posts/themes/(?P<type>[a-zA-Z0-9-]+)', array(
|
37 |
+
'methods' => 'GET',
|
38 |
+
'callback' => array( $this, 'get_gutenberg_themes' ),
|
39 |
+
'permission_callback' => function () {
|
40 |
+
return current_user_can( 'edit_posts' );
|
41 |
+
},
|
42 |
+
'args' => array(
|
43 |
+
'type' => array(),
|
44 |
+
),
|
45 |
+
) );
|
46 |
+
|
47 |
+
register_rest_route( 'exactmetrics/v1', '/terms/(?P<slug>[a-zA-Z0-9-_]+)', array(
|
48 |
+
'methods' => 'GET',
|
49 |
+
'callback' => array( $this, 'get_taxonomy_terms' ),
|
50 |
+
'permission_callback' => function () {
|
51 |
+
return current_user_can( 'edit_posts' );
|
52 |
+
},
|
53 |
+
'args' => array(
|
54 |
+
'slug' => array(),
|
55 |
+
),
|
56 |
+
) );
|
57 |
+
|
58 |
+
register_rest_route( 'exactmetrics/v1', '/taxonomy/(?P<slug>[a-zA-Z0-9-_]+)', array(
|
59 |
+
'methods' => 'GET',
|
60 |
+
'callback' => array( $this, 'get_taxonomy' ),
|
61 |
+
'permission_callback' => function () {
|
62 |
+
return current_user_can( 'edit_posts' );
|
63 |
+
},
|
64 |
+
'args' => array(
|
65 |
+
'slug' => array(),
|
66 |
+
),
|
67 |
+
) );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Get the themes for Gutenberg (use the specific nonce).
|
72 |
+
*/
|
73 |
+
public function get_gutenberg_themes( $data ) {
|
74 |
+
|
75 |
+
$type = ! empty( $data['type'] ) ? $data['type'] : 'inline';
|
76 |
+
|
77 |
+
return $this->get_themes_by_type( $type );
|
78 |
+
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get the themes for a specific type using ajax.
|
83 |
+
*/
|
84 |
+
public function ajax_get_themes() {
|
85 |
+
|
86 |
+
check_ajax_referer( 'mi-admin-nonce', 'nonce' );
|
87 |
+
|
88 |
+
$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : 'inline';
|
89 |
+
|
90 |
+
wp_send_json_success( $this->get_themes_by_type( $type, false ) );
|
91 |
+
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Helper to get themes by type.
|
96 |
+
*
|
97 |
+
* @param string $type The widget type: inline/widget/products.
|
98 |
+
* @param bool $styled Whether to style the selected theme or not.
|
99 |
+
*
|
100 |
+
* @return array
|
101 |
+
*/
|
102 |
+
public function get_themes_by_type( $type, $styled = true ) {
|
103 |
+
$theme = '';
|
104 |
+
|
105 |
+
if ( $styled ) {
|
106 |
+
if ( 'inline' === $type ) {
|
107 |
+
$theme = ExactMetrics_Popular_Posts_Inline()->theme;
|
108 |
+
}
|
109 |
+
|
110 |
+
if ( 'widget' === $type ) {
|
111 |
+
$theme = ExactMetrics_Popular_Posts_Widget()->theme;
|
112 |
+
}
|
113 |
+
}
|
114 |
+
$themes = $this->get_themes( $type, $theme );
|
115 |
+
$themes_array = $themes->themes;
|
116 |
+
|
117 |
+
if ( isset( $themes_array[ $theme ] ) && $styled ) {
|
118 |
+
$themes_array[ $theme ] = $themes->get_theme();
|
119 |
+
}
|
120 |
+
|
121 |
+
$response = array(
|
122 |
+
'themes' => $themes_array,
|
123 |
+
'selected' => $theme,
|
124 |
+
);
|
125 |
+
|
126 |
+
return $response;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Get themes by type.
|
131 |
+
*
|
132 |
+
* @param string $type The widget type: inline/widget/products.
|
133 |
+
* @param string $theme The selected theme.
|
134 |
+
*
|
135 |
+
* @return ExactMetrics_Popular_Posts_Themes
|
136 |
+
*/
|
137 |
+
public function get_themes( $type, $theme ) {
|
138 |
+
|
139 |
+
$themes_object = new ExactMetrics_Popular_Posts_Themes( $type, $theme );
|
140 |
+
|
141 |
+
return $themes_object;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Get a specific theme details.
|
146 |
+
*
|
147 |
+
* @param string $type The widget type: inline/widget/products.
|
148 |
+
* @param string $theme The selected theme.
|
149 |
+
*
|
150 |
+
* @return array|mixed
|
151 |
+
*/
|
152 |
+
public function get_theme_details( $type, $theme ) {
|
153 |
+
|
154 |
+
$themes = new ExactMetrics_Popular_Posts_Themes( $type, $theme );
|
155 |
+
|
156 |
+
return $themes->get_theme();
|
157 |
+
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Handler for loading taxonomy terms using a custom endpoint.
|
162 |
+
*
|
163 |
+
* @param array $data Data passed from the request.
|
164 |
+
*
|
165 |
+
* @return array
|
166 |
+
*/
|
167 |
+
public function get_taxonomy_terms( $data ) {
|
168 |
+
|
169 |
+
$slug = ! empty( $data['slug'] ) ? $data['slug'] : 'category';
|
170 |
+
|
171 |
+
$terms = get_terms( array(
|
172 |
+
'taxonomy' => $slug,
|
173 |
+
) );
|
174 |
+
|
175 |
+
$return = array();
|
176 |
+
|
177 |
+
if ( ! is_wp_error( $terms ) ) {
|
178 |
+
foreach ( $terms as $term ) {
|
179 |
+
$return[] = array(
|
180 |
+
'id' => $term->term_id,
|
181 |
+
'name' => $term->name,
|
182 |
+
'parent' => $term->parent,
|
183 |
+
);
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
return $return;
|
188 |
+
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Get details for a taxonomy so we can use it in the Gutenberg block.
|
193 |
+
*
|
194 |
+
* @param array $data Data passed from the request.
|
195 |
+
*
|
196 |
+
* @return false|WP_Taxonomy
|
197 |
+
*/
|
198 |
+
public function get_taxonomy( $data ) {
|
199 |
+
|
200 |
+
$slug = ! empty( $data['slug'] ) ? $data['slug'] : 'category';
|
201 |
+
|
202 |
+
return get_taxonomy( $slug );
|
203 |
+
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Ajax handler to empty the Popular Posts cache for all instances.
|
208 |
+
*/
|
209 |
+
public function empty_cache() {
|
210 |
+
|
211 |
+
check_ajax_referer( 'mi-admin-nonce', 'nonce' );
|
212 |
+
|
213 |
+
if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
|
214 |
+
return;
|
215 |
+
}
|
216 |
+
|
217 |
+
$types = array(
|
218 |
+
'inline',
|
219 |
+
'widget',
|
220 |
+
'products',
|
221 |
+
);
|
222 |
+
|
223 |
+
foreach ( $types as $type ) {
|
224 |
+
delete_option( 'exactmetrics_popular_posts_cache_' . $type );
|
225 |
+
}
|
226 |
+
|
227 |
+
wp_send_json_success();
|
228 |
+
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Ajax handler to get the output for Popular Posts widgets from the JSON data on the frontend.
|
233 |
+
*/
|
234 |
+
public function get_ajax_output() {
|
235 |
+
|
236 |
+
if ( empty( $_POST['data'] ) || ! is_array( $_POST['data'] ) ) {
|
237 |
+
return;
|
238 |
+
}
|
239 |
+
|
240 |
+
$html = array();
|
241 |
+
$widgets_args = $_POST['data'];
|
242 |
+
|
243 |
+
foreach ( $widgets_args as $args ) {
|
244 |
+
$args = json_decode( sanitize_text_field( wp_unslash( $args ) ), true );
|
245 |
+
if ( ! empty( $args['type'] ) ) {
|
246 |
+
$type = ucfirst( $args['type'] );
|
247 |
+
$widget_function = function_exists( 'ExactMetrics_Popular_Posts_' . $type ) ? call_user_func( 'ExactMetrics_Popular_Posts_' . $type ) : false;
|
248 |
+
if ( $widget_function ) {
|
249 |
+
$html[] = $widget_function->get_rendered_html( $args );
|
250 |
+
}
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
wp_send_json( $html );
|
255 |
+
}
|
256 |
+
|
257 |
+
}
|
258 |
+
|
259 |
+
new ExactMetrics_Popular_Posts_Ajax();
|
lite/includes/popular-posts/class-popular-posts-cache.php
CHANGED
@@ -1,131 +1,131 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* This class is used for handling Popular Posts caching.
|
4 |
-
*
|
5 |
-
* @package ExactMetrics
|
6 |
-
*/
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class ExactMetrics_Popular_Posts_Cache
|
10 |
-
*/
|
11 |
-
class ExactMetrics_Popular_Posts_Cache {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Instance type (inline/widget/products).
|
15 |
-
*
|
16 |
-
* @var string
|
17 |
-
*/
|
18 |
-
public $type;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* ExactMetrics_Popular_Posts_Cache constructor.
|
22 |
-
*
|
23 |
-
* @param string $type The instance type (inline/widget/products).
|
24 |
-
*/
|
25 |
-
public function __construct( $type ) {
|
26 |
-
|
27 |
-
$this->type = $type;
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Build an unique key from the arguments so we can cache different instances.
|
32 |
-
* This way, the Gutenberg block or the sidebar widget get cached with their own query settings
|
33 |
-
* if they are different from the ones set in Vue.
|
34 |
-
*
|
35 |
-
* @param $args
|
36 |
-
*
|
37 |
-
* @return string
|
38 |
-
*/
|
39 |
-
public function get_args_key( $args ) {
|
40 |
-
return md5( wp_json_encode( $args ) );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Get the specific options key for the set type.
|
45 |
-
*
|
46 |
-
* @return string
|
47 |
-
*/
|
48 |
-
public function get_cache_key() {
|
49 |
-
return 'exactmetrics_popular_posts_cache_' . $this->type;
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Get cached posts data and check expiration. Each query result is stored with the timestamp and that
|
54 |
-
* is used to compare to the current settings for expiration.
|
55 |
-
*
|
56 |
-
* @param array $args This is an array with query parameters for WP_Query used to identify if this query has been cached.
|
57 |
-
*
|
58 |
-
* @return array
|
59 |
-
*/
|
60 |
-
public function get_cached_posts( $args ) {
|
61 |
-
|
62 |
-
$cache_refresh_days = $this->get_cache_interval();
|
63 |
-
$cached_data = get_option( $this->get_cache_key(), array() );
|
64 |
-
$args_key = $this->get_args_key( $args ); // Generate an unique key based on the instance settings.
|
65 |
-
|
66 |
-
if ( isset( $cached_data[ $args_key ] ) && isset( $cached_data[ $args_key ]['saved_at'] ) ) {
|
67 |
-
$time_since = time() - $cached_data[ $args_key ]['saved_at'];
|
68 |
-
|
69 |
-
if ( $time_since < intval( $cache_refresh_days ) * DAY_IN_SECONDS ) {
|
70 |
-
return $cached_data[ $args_key ]['posts'];
|
71 |
-
} else {
|
72 |
-
// It's expired so let's delete it.
|
73 |
-
unset( $cached_data[ $args_key ] );
|
74 |
-
update_option( $this->get_cache_key(), $cached_data );
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
return array();
|
79 |
-
|
80 |
-
}
|
81 |
-
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Get the option set in the settings for cache expiration.
|
85 |
-
*
|
86 |
-
* @return int
|
87 |
-
*/
|
88 |
-
private function get_cache_interval() {
|
89 |
-
$cache_refresh_days = exactmetrics_get_option( 'popular_posts_caching_refresh', 7 );
|
90 |
-
|
91 |
-
// If they downgraded and previously used a custom interval use the default 7 until the update the option.
|
92 |
-
if ( 'custom' === $cache_refresh_days ) {
|
93 |
-
$cache_refresh_days = 7;
|
94 |
-
}
|
95 |
-
|
96 |
-
return intval( $cache_refresh_days );
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Store a query result in the cache along with the arguments used to grab them.
|
101 |
-
*
|
102 |
-
* @param array $args Arguments used in WP_Query used to build an unique key for the loaded data.
|
103 |
-
* @param array $posts An array of posts that resulted from the query to be saved in the cache.
|
104 |
-
*/
|
105 |
-
public function save_posts_to_cache( $args, $posts ) {
|
106 |
-
|
107 |
-
if ( empty( $posts ) ) {
|
108 |
-
// Don't save empty posts.
|
109 |
-
return;
|
110 |
-
}
|
111 |
-
|
112 |
-
$args_key = md5( wp_json_encode( $args ) ); // Generate an unique key based on the instance settings.
|
113 |
-
$cached_data = get_option( $this->get_cache_key(), array() );
|
114 |
-
|
115 |
-
$cached_data[ $args_key ] = array(
|
116 |
-
'saved_at' => time(),
|
117 |
-
'posts' => $posts,
|
118 |
-
);
|
119 |
-
|
120 |
-
update_option( $this->get_cache_key(), $cached_data );
|
121 |
-
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Delete database option for cache.
|
126 |
-
*/
|
127 |
-
public function delete_data() {
|
128 |
-
delete_option( $this->get_cache_key() );
|
129 |
-
}
|
130 |
-
|
131 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This class is used for handling Popular Posts caching.
|
4 |
+
*
|
5 |
+
* @package ExactMetrics
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class ExactMetrics_Popular_Posts_Cache
|
10 |
+
*/
|
11 |
+
class ExactMetrics_Popular_Posts_Cache {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Instance type (inline/widget/products).
|
15 |
+
*
|
16 |
+
* @var string
|
17 |
+
*/
|
18 |
+
public $type;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* ExactMetrics_Popular_Posts_Cache constructor.
|
22 |
+
*
|
23 |
+
* @param string $type The instance type (inline/widget/products).
|
24 |
+
*/
|
25 |
+
public function __construct( $type ) {
|
26 |
+
|
27 |
+
$this->type = $type;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Build an unique key from the arguments so we can cache different instances.
|
32 |
+
* This way, the Gutenberg block or the sidebar widget get cached with their own query settings
|
33 |
+
* if they are different from the ones set in Vue.
|
34 |
+
*
|
35 |
+
* @param $args
|
36 |
+
*
|
37 |
+
* @return string
|
38 |
+
*/
|
39 |
+
public function get_args_key( $args ) {
|
40 |
+
return md5( wp_json_encode( $args ) );
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Get the specific options key for the set type.
|
45 |
+
*
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
+
public function get_cache_key() {
|
49 |
+
return 'exactmetrics_popular_posts_cache_' . $this->type;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Get cached posts data and check expiration. Each query result is stored with the timestamp and that
|
54 |
+
* is used to compare to the current settings for expiration.
|
55 |
+
*
|
56 |
+
* @param array $args This is an array with query parameters for WP_Query used to identify if this query has been cached.
|
57 |
+
*
|
58 |
+
* @return array
|
59 |
+
*/
|
60 |
+
public function get_cached_posts( $args ) {
|
61 |
+
|
62 |
+
$cache_refresh_days = $this->get_cache_interval();
|
63 |
+
$cached_data = get_option( $this->get_cache_key(), array() );
|
64 |
+
$args_key = $this->get_args_key( $args ); // Generate an unique key based on the instance settings.
|
65 |
+
|
66 |
+
if ( isset( $cached_data[ $args_key ] ) && isset( $cached_data[ $args_key ]['saved_at'] ) ) {
|
67 |
+
$time_since = time() - $cached_data[ $args_key ]['saved_at'];
|
68 |
+
|
69 |
+
if ( $time_since < intval( $cache_refresh_days ) * DAY_IN_SECONDS ) {
|
70 |
+
return $cached_data[ $args_key ]['posts'];
|
71 |
+
} else {
|
72 |
+
// It's expired so let's delete it.
|
73 |
+
unset( $cached_data[ $args_key ] );
|
74 |
+
update_option( $this->get_cache_key(), $cached_data );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
return array();
|
79 |
+
|
80 |
+
}
|
81 |
+
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Get the option set in the settings for cache expiration.
|
85 |
+
*
|
86 |
+
* @return int
|
87 |
+
*/
|
88 |
+
private function get_cache_interval() {
|
89 |
+
$cache_refresh_days = exactmetrics_get_option( 'popular_posts_caching_refresh', 7 );
|
90 |
+
|
91 |
+
// If they downgraded and previously used a custom interval use the default 7 until the update the option.
|
92 |
+
if ( 'custom' === $cache_refresh_days ) {
|
93 |
+
$cache_refresh_days = 7;
|
94 |
+
}
|
95 |
+
|
96 |
+
return intval( $cache_refresh_days );
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Store a query result in the cache along with the arguments used to grab them.
|
101 |
+
*
|
102 |
+
* @param array $args Arguments used in WP_Query used to build an unique key for the loaded data.
|
103 |
+
* @param array $posts An array of posts that resulted from the query to be saved in the cache.
|
104 |
+
*/
|
105 |
+
public function save_posts_to_cache( $args, $posts ) {
|
106 |
+
|
107 |
+
if ( empty( $posts ) ) {
|
108 |
+
// Don't save empty posts.
|
109 |
+
return;
|
110 |
+
}
|
111 |
+
|
112 |
+
$args_key = md5( wp_json_encode( $args ) ); // Generate an unique key based on the instance settings.
|
113 |
+
$cached_data = get_option( $this->get_cache_key(), array() );
|
114 |
+
|
115 |
+
$cached_data[ $args_key ] = array(
|
116 |
+
'saved_at' => time(),
|
117 |
+
'posts' => $posts,
|
118 |
+
);
|
119 |
+
|
120 |
+
update_option( $this->get_cache_key(), $cached_data );
|
121 |
+
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Delete database option for cache.
|
126 |
+
*/
|
127 |
+
public function delete_data() {
|
128 |
+
delete_option( $this->get_cache_key() );
|
129 |
+
}
|
130 |
+
|
131 |
+
}
|
lite/includes/popular-posts/class-popular-posts-inline.php
CHANGED
@@ -1,270 +1,270 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Code specific to the inline Popular Posts widget type.
|
4 |
-
*/
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class ExactMetrics_Popular_Posts_Inline
|
8 |
-
*/
|
9 |
-
class ExactMetrics_Popular_Posts_Inline extends ExactMetrics_Popular_Posts {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Used to load the setting specific for this class.
|
13 |
-
*
|
14 |
-
* @var string
|
15 |
-
*/
|
16 |
-
protected $settings_key = 'popular_posts_inline';
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Used for registering the shortcode specific to this class.
|
20 |
-
*
|
21 |
-
* @var string
|
22 |
-
*/
|
23 |
-
protected $shortcode_key = 'exactmetrics_popular_posts_inline';
|
24 |
-
|
25 |
-
/**
|
26 |
-
* The instance type. Used for loading specific settings.
|
27 |
-
*
|
28 |
-
* @var string
|
29 |
-
*/
|
30 |
-
protected $type = 'inline';
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Inline-specific hooks.
|
34 |
-
*/
|
35 |
-
public function hooks() {
|
36 |
-
parent::hooks();
|
37 |
-
|
38 |
-
add_action( 'wp', array( $this, 'maybe_auto_insert' ) );
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Get the rendered HTML for output.
|
43 |
-
*
|
44 |
-
* @param array $atts These are attributes used to build the specific instance, they can be either shortcode
|
45 |
-
* attributes or Gutenberg block props.
|
46 |
-
*
|
47 |
-
* @return string
|
48 |
-
*/
|
49 |
-
public function get_rendered_html( $atts ) {
|
50 |
-
|
51 |
-
$theme = $this->theme;
|
52 |
-
if ( ! empty( $atts['theme'] ) ) {
|
53 |
-
$theme = $atts['theme'];
|
54 |
-
}
|
55 |
-
|
56 |
-
$theme = $this->is_theme_available( $theme );
|
57 |
-
|
58 |
-
$posts = $this->get_posts_to_display();
|
59 |
-
|
60 |
-
if ( empty( $posts ) ) {
|
61 |
-
return '';
|
62 |
-
}
|
63 |
-
|
64 |
-
if ( 'curated' === $this->sort && apply_filters( 'exactmetrics_popular_posts_inline_curated_shuffle', true ) ) {
|
65 |
-
// Randomize the order.
|
66 |
-
shuffle( $posts );
|
67 |
-
}
|
68 |
-
|
69 |
-
$theme_styles = $this->get_theme_props( $theme )->get_theme();
|
70 |
-
$limit = ! empty( $theme_styles['posts'] ) ? $theme_styles['posts'] : 1;
|
71 |
-
|
72 |
-
$label_text = '';
|
73 |
-
if ( isset( $theme_styles['styles']['label'] ) ) {
|
74 |
-
$label_text = isset( $atts['labelText'] ) ? $atts['labelText'] : $theme_styles['styles']['label']['text'];
|
75 |
-
}
|
76 |
-
|
77 |
-
// Wrap in a P tag to keep the same spacing.
|
78 |
-
$html = '<div class="' . $this->get_wrapper_class( $atts ) . '" ' . $this->get_element_style( $theme, 'background', $atts ) . '>';
|
79 |
-
|
80 |
-
if ( ! empty( $theme_styles['image'] ) && ! empty( $posts[0]['image'] ) ) {
|
81 |
-
$html .= '<div class="exactmetrics-inline-popular-posts-image">';
|
82 |
-
$html .= '<img src="' . $posts[0]['image'] . '" srcset=" ' . $posts[0]['srcset'] . ' " alt="' . esc_attr( $posts[0]['title'] ) . '" />';
|
83 |
-
$html .= '</div>';
|
84 |
-
}
|
85 |
-
$html .= '<div class="exactmetrics-inline-popular-posts-text">';
|
86 |
-
if ( ! empty( $theme_styles['styles']['icon'] ) ) {
|
87 |
-
$html .= '<span class="exactmetrics-inline-popular-posts-icon" style=""><svg width="14" height="19" viewBox="0 0 14 19" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.875 0.899463C7.875 1.59183 8.0816 2.24711 8.49479 2.8653C8.93229 3.48349 9.44271 4.06458 10.026 4.60859C10.6337 5.15259 11.2292 5.73369 11.8125 6.35188C12.4201 6.97007 12.9306 7.76135 13.3438 8.72572C13.7812 9.66537 14 10.7163 14 11.8785C14 13.832 13.3073 15.5011 11.9219 16.8858C10.5608 18.2953 8.92014 19 7 19C5.07986 19 3.42708 18.2953 2.04167 16.8858C0.680556 15.5011 0 13.832 0 11.8785C0 9.94973 0.668403 8.28062 2.00521 6.87116C2.27257 6.57443 2.58854 6.50024 2.95312 6.64861C3.31771 6.79697 3.5 7.08134 3.5 7.50171V10.6545C3.5 11.3221 3.71875 11.8908 4.15625 12.3607C4.61806 12.8305 5.16493 13.0654 5.79688 13.0654C6.45312 13.0654 7.01215 12.8428 7.47396 12.3978C7.93576 11.9279 8.16667 11.3592 8.16667 10.6916C8.16667 10.2712 8.04514 9.86318 7.80208 9.46754C7.58333 9.0719 7.31597 8.71336 7 8.3919C6.68403 8.07044 6.34375 7.73662 5.97917 7.39043C5.63889 7.04425 5.34722 6.66097 5.10417 6.2406C4.88542 5.82024 4.73958 5.35041 4.66667 4.83114C4.59375 4.31186 4.67882 3.68131 4.92188 2.93948C5.18924 2.17293 5.63889 1.33219 6.27083 0.417277C6.51389 0.0463641 6.84201 -0.0772735 7.25521 0.0463641C7.6684 0.170002 7.875 0.454368 7.875 0.899463Z" fill="#EB5757"></path></svg></span>';
|
88 |
-
}
|
89 |
-
if ( ! empty( $theme_styles['styles']['label'] ) ) {
|
90 |
-
$html .= '<span class="exactmetrics-inline-popular-posts-label" ' . $this->get_element_style( $theme, 'label', $atts ) . '>' . $label_text . '</span>';
|
91 |
-
}
|
92 |
-
if ( ! empty( $theme_styles['styles']['border'] ) ) {
|
93 |
-
$html .= '<span class="exactmetrics-inline-popular-posts-border" ' . $this->get_element_style( $theme, 'border', $atts, 'color' ) . '></span>';
|
94 |
-
}
|
95 |
-
if ( ! empty( $theme_styles['styles']['border']['color2'] ) ) {
|
96 |
-
$html .= '<span class="exactmetrics-inline-popular-posts-border-2" ' . $this->get_element_style( $theme, 'border', $atts, 'color2' ) . '></span>';
|
97 |
-
}
|
98 |
-
|
99 |
-
$display_count = 0;
|
100 |
-
foreach ( $posts as $post ) {
|
101 |
-
$display_count ++;
|
102 |
-
if ( $display_count > $limit ) {
|
103 |
-
break;
|
104 |
-
}
|
105 |
-
$this->set_post_shown( $post['id'] );
|
106 |
-
$html .= '<div class="exactmetrics-inline-popular-posts-post">';
|
107 |
-
$html .= '<a class="exactmetrics-inline-popular-posts-title" ' . $this->get_element_style( $theme, 'title', $atts ) . ' href="' . $post['link'] . '">' . $post['title'] . '</a>';
|
108 |
-
$html .= '</div>';
|
109 |
-
}
|
110 |
-
|
111 |
-
$html .= '</div>';// Text div.
|
112 |
-
$html .= '</div><p></p>';// Main div.
|
113 |
-
|
114 |
-
return $html;
|
115 |
-
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Specific inline styles based on theme settings.
|
120 |
-
*
|
121 |
-
* @return string
|
122 |
-
*/
|
123 |
-
public function build_inline_styles() {
|
124 |
-
|
125 |
-
$themes = $this->get_themes_styles_for_output();
|
126 |
-
$styles = '';
|
127 |
-
|
128 |
-
foreach ( $themes as $theme_key => $theme_styles ) {
|
129 |
-
if ( ! empty( $theme_styles['background'] ) ) {
|
130 |
-
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' {';
|
131 |
-
|
132 |
-
if ( ! empty( $theme_styles['background']['color'] ) ) {
|
133 |
-
$styles .= 'background-color:' . $theme_styles['background']['color'] . ';';
|
134 |
-
}
|
135 |
-
if ( ! empty( $theme_styles['background']['border'] ) ) {
|
136 |
-
$styles .= 'border-color:' . $theme_styles['background']['border'] . ';';
|
137 |
-
}
|
138 |
-
|
139 |
-
$styles .= '}';
|
140 |
-
}
|
141 |
-
|
142 |
-
if ( ! empty( $theme_styles['label'] ) ) {
|
143 |
-
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-label {';
|
144 |
-
|
145 |
-
if ( ! empty( $theme_styles['label']['color'] ) ) {
|
146 |
-
$styles .= 'color:' . $theme_styles['label']['color'] . ';';
|
147 |
-
}
|
148 |
-
|
149 |
-
if ( ! empty( $theme_styles['label']['background'] ) ) {
|
150 |
-
$styles .= 'background-color:' . $theme_styles['label']['background'] . ';';
|
151 |
-
}
|
152 |
-
|
153 |
-
$styles .= '}';
|
154 |
-
}
|
155 |
-
|
156 |
-
if ( ! empty( $theme_styles['title'] ) ) {
|
157 |
-
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-title {';
|
158 |
-
|
159 |
-
if ( ! empty( $theme_styles['title']['color'] ) ) {
|
160 |
-
$styles .= 'color:' . $theme_styles['title']['color'] . ';';
|
161 |
-
}
|
162 |
-
if ( ! empty( $theme_styles['title']['size'] ) ) {
|
163 |
-
$styles .= 'font-size:' . $theme_styles['title']['size'] . 'px;';
|
164 |
-
}
|
165 |
-
|
166 |
-
$styles .= '}';
|
167 |
-
}
|
168 |
-
|
169 |
-
if ( ! empty( $theme_styles['border'] ) ) {
|
170 |
-
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-border {';
|
171 |
-
|
172 |
-
if ( ! empty( $theme_styles['border']['color'] ) ) {
|
173 |
-
$styles .= 'border-color:' . $theme_styles['border']['color'] . ';';
|
174 |
-
}
|
175 |
-
|
176 |
-
$styles .= '}';
|
177 |
-
}
|
178 |
-
}
|
179 |
-
|
180 |
-
return $styles;
|
181 |
-
}
|
182 |
-
|
183 |
-
/**
|
184 |
-
* Check if we should attempt to automatically insert the inline widget.
|
185 |
-
*/
|
186 |
-
public function maybe_auto_insert() {
|
187 |
-
|
188 |
-
$post_types = $this->post_types;
|
189 |
-
if ( ! empty( $post_types ) && is_singular( $post_types ) && 'automatic' === $this->placement ) {
|
190 |
-
add_filter( 'the_content', array( $this, 'add_inline_posts_to_content' ) );
|
191 |
-
}
|
192 |
-
|
193 |
-
}
|
194 |
-
|
195 |
-
/**
|
196 |
-
* Insert the widget in the content.
|
197 |
-
*
|
198 |
-
* @param string $content The post content.
|
199 |
-
*
|
200 |
-
* @return string
|
201 |
-
*/
|
202 |
-
public function add_inline_posts_to_content(
|
203 |
-
$content
|
204 |
-
) {
|
205 |
-
|
206 |
-
if ( $this->is_post_excluded() ) {
|
207 |
-
return $content;
|
208 |
-
}
|
209 |
-
|
210 |
-
$words_count = str_word_count( $content );
|
211 |
-
$after_count = intval( $this->after_count );
|
212 |
-
|
213 |
-
// Insert only if there are more words then the insert after value.
|
214 |
-
if ( $words_count > $after_count ) {
|
215 |
-
|
216 |
-
$words = explode( ' ', $content );
|
217 |
-
$count = 0;
|
218 |
-
|
219 |
-
foreach ( $words as $index => $word ) {
|
220 |
-
$count ++;
|
221 |
-
if ( $count > $after_count ) {
|
222 |
-
$p_index = strpos( $word, '</p>' );
|
223 |
-
// Make sure the paragraph tag is not wrapped in another element like a blockquote.
|
224 |
-
if ( false !== $p_index && false === strpos( $word, '</p></' ) ) {
|
225 |
-
$words[ $index ] = substr_replace( $word, $this->shortcode_output( array() ), $p_index + 4, 0 );
|
226 |
-
$this->posts = array();
|
227 |
-
break;
|
228 |
-
}
|
229 |
-
}
|
230 |
-
}
|
231 |
-
|
232 |
-
$content = implode( ' ', $words );
|
233 |
-
|
234 |
-
}
|
235 |
-
|
236 |
-
return $content;
|
237 |
-
}
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Check if the selected theme is available with the current license to avoid showing a theme not available.
|
241 |
-
* Returns the default 'alpha' theme if not available.
|
242 |
-
*
|
243 |
-
* @param string $theme Theme slug for which we are checking.
|
244 |
-
*
|
245 |
-
* @return string
|
246 |
-
*/
|
247 |
-
public function is_theme_available( $theme ) {
|
248 |
-
|
249 |
-
$theme_props = $this->get_theme_props( $theme )->get_theme();
|
250 |
-
|
251 |
-
if ( ! empty( $theme_props['level'] ) && 'lite' === $theme_props['level'] ) {
|
252 |
-
return $theme;
|
253 |
-
}
|
254 |
-
|
255 |
-
return 'alpha';
|
256 |
-
|
257 |
-
}
|
258 |
-
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* Get the current class in a function.
|
263 |
-
*
|
264 |
-
* @return ExactMetrics_Popular_Posts_Inline Instance of the current class.
|
265 |
-
*/
|
266 |
-
function ExactMetrics_Popular_Posts_Inline() {
|
267 |
-
return ExactMetrics_Popular_Posts_Inline::get_instance();
|
268 |
-
}
|
269 |
-
|
270 |
-
ExactMetrics_Popular_Posts_Inline();
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Code specific to the inline Popular Posts widget type.
|
4 |
+
*/
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class ExactMetrics_Popular_Posts_Inline
|
8 |
+
*/
|
9 |
+
class ExactMetrics_Popular_Posts_Inline extends ExactMetrics_Popular_Posts {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Used to load the setting specific for this class.
|
13 |
+
*
|
14 |
+
* @var string
|
15 |
+
*/
|
16 |
+
protected $settings_key = 'popular_posts_inline';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Used for registering the shortcode specific to this class.
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
protected $shortcode_key = 'exactmetrics_popular_posts_inline';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The instance type. Used for loading specific settings.
|
27 |
+
*
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $type = 'inline';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Inline-specific hooks.
|
34 |
+
*/
|
35 |
+
public function hooks() {
|
36 |
+
parent::hooks();
|
37 |
+
|
38 |
+
add_action( 'wp', array( $this, 'maybe_auto_insert' ) );
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Get the rendered HTML for output.
|
43 |
+
*
|
44 |
+
* @param array $atts These are attributes used to build the specific instance, they can be either shortcode
|
45 |
+
* attributes or Gutenberg block props.
|
46 |
+
*
|
47 |
+
* @return string
|
48 |
+
*/
|
49 |
+
public function get_rendered_html( $atts ) {
|
50 |
+
|
51 |
+
$theme = $this->theme;
|
52 |
+
if ( ! empty( $atts['theme'] ) ) {
|
53 |
+
$theme = $atts['theme'];
|
54 |
+
}
|
55 |
+
|
56 |
+
$theme = $this->is_theme_available( $theme );
|
57 |
+
|
58 |
+
$posts = $this->get_posts_to_display();
|
59 |
+
|
60 |
+
if ( empty( $posts ) ) {
|
61 |
+
return '';
|
62 |
+
}
|
63 |
+
|
64 |
+
if ( 'curated' === $this->sort && apply_filters( 'exactmetrics_popular_posts_inline_curated_shuffle', true ) ) {
|
65 |
+
// Randomize the order.
|
66 |
+
shuffle( $posts );
|
67 |
+
}
|
68 |
+
|
69 |
+
$theme_styles = $this->get_theme_props( $theme )->get_theme();
|
70 |
+
$limit = ! empty( $theme_styles['posts'] ) ? $theme_styles['posts'] : 1;
|
71 |
+
|
72 |
+
$label_text = '';
|
73 |
+
if ( isset( $theme_styles['styles']['label'] ) ) {
|
74 |
+
$label_text = isset( $atts['labelText'] ) ? $atts['labelText'] : $theme_styles['styles']['label']['text'];
|
75 |
+
}
|
76 |
+
|
77 |
+
// Wrap in a P tag to keep the same spacing.
|
78 |
+
$html = '<div class="' . $this->get_wrapper_class( $atts ) . '" ' . $this->get_element_style( $theme, 'background', $atts ) . '>';
|
79 |
+
|
80 |
+
if ( ! empty( $theme_styles['image'] ) && ! empty( $posts[0]['image'] ) ) {
|
81 |
+
$html .= '<div class="exactmetrics-inline-popular-posts-image">';
|
82 |
+
$html .= '<img src="' . $posts[0]['image'] . '" srcset=" ' . $posts[0]['srcset'] . ' " alt="' . esc_attr( $posts[0]['title'] ) . '" />';
|
83 |
+
$html .= '</div>';
|
84 |
+
}
|
85 |
+
$html .= '<div class="exactmetrics-inline-popular-posts-text">';
|
86 |
+
if ( ! empty( $theme_styles['styles']['icon'] ) ) {
|
87 |
+
$html .= '<span class="exactmetrics-inline-popular-posts-icon" style=""><svg width="14" height="19" viewBox="0 0 14 19" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.875 0.899463C7.875 1.59183 8.0816 2.24711 8.49479 2.8653C8.93229 3.48349 9.44271 4.06458 10.026 4.60859C10.6337 5.15259 11.2292 5.73369 11.8125 6.35188C12.4201 6.97007 12.9306 7.76135 13.3438 8.72572C13.7812 9.66537 14 10.7163 14 11.8785C14 13.832 13.3073 15.5011 11.9219 16.8858C10.5608 18.2953 8.92014 19 7 19C5.07986 19 3.42708 18.2953 2.04167 16.8858C0.680556 15.5011 0 13.832 0 11.8785C0 9.94973 0.668403 8.28062 2.00521 6.87116C2.27257 6.57443 2.58854 6.50024 2.95312 6.64861C3.31771 6.79697 3.5 7.08134 3.5 7.50171V10.6545C3.5 11.3221 3.71875 11.8908 4.15625 12.3607C4.61806 12.8305 5.16493 13.0654 5.79688 13.0654C6.45312 13.0654 7.01215 12.8428 7.47396 12.3978C7.93576 11.9279 8.16667 11.3592 8.16667 10.6916C8.16667 10.2712 8.04514 9.86318 7.80208 9.46754C7.58333 9.0719 7.31597 8.71336 7 8.3919C6.68403 8.07044 6.34375 7.73662 5.97917 7.39043C5.63889 7.04425 5.34722 6.66097 5.10417 6.2406C4.88542 5.82024 4.73958 5.35041 4.66667 4.83114C4.59375 4.31186 4.67882 3.68131 4.92188 2.93948C5.18924 2.17293 5.63889 1.33219 6.27083 0.417277C6.51389 0.0463641 6.84201 -0.0772735 7.25521 0.0463641C7.6684 0.170002 7.875 0.454368 7.875 0.899463Z" fill="#EB5757"></path></svg></span>';
|
88 |
+
}
|
89 |
+
if ( ! empty( $theme_styles['styles']['label'] ) ) {
|
90 |
+
$html .= '<span class="exactmetrics-inline-popular-posts-label" ' . $this->get_element_style( $theme, 'label', $atts ) . '>' . $label_text . '</span>';
|
91 |
+
}
|
92 |
+
if ( ! empty( $theme_styles['styles']['border'] ) ) {
|
93 |
+
$html .= '<span class="exactmetrics-inline-popular-posts-border" ' . $this->get_element_style( $theme, 'border', $atts, 'color' ) . '></span>';
|
94 |
+
}
|
95 |
+
if ( ! empty( $theme_styles['styles']['border']['color2'] ) ) {
|
96 |
+
$html .= '<span class="exactmetrics-inline-popular-posts-border-2" ' . $this->get_element_style( $theme, 'border', $atts, 'color2' ) . '></span>';
|
97 |
+
}
|
98 |
+
|
99 |
+
$display_count = 0;
|
100 |
+
foreach ( $posts as $post ) {
|
101 |
+
$display_count ++;
|
102 |
+
if ( $display_count > $limit ) {
|
103 |
+
break;
|
104 |
+
}
|
105 |
+
$this->set_post_shown( $post['id'] );
|
106 |
+
$html .= '<div class="exactmetrics-inline-popular-posts-post">';
|
107 |
+
$html .= '<a class="exactmetrics-inline-popular-posts-title" ' . $this->get_element_style( $theme, 'title', $atts ) . ' href="' . $post['link'] . '">' . $post['title'] . '</a>';
|
108 |
+
$html .= '</div>';
|
109 |
+
}
|
110 |
+
|
111 |
+
$html .= '</div>';// Text div.
|
112 |
+
$html .= '</div><p></p>';// Main div.
|
113 |
+
|
114 |
+
return $html;
|
115 |
+
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Specific inline styles based on theme settings.
|
120 |
+
*
|
121 |
+
* @return string
|
122 |
+
*/
|
123 |
+
public function build_inline_styles() {
|
124 |
+
|
125 |
+
$themes = $this->get_themes_styles_for_output();
|
126 |
+
$styles = '';
|
127 |
+
|
128 |
+
foreach ( $themes as $theme_key => $theme_styles ) {
|
129 |
+
if ( ! empty( $theme_styles['background'] ) ) {
|
130 |
+
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' {';
|
131 |
+
|
132 |
+
if ( ! empty( $theme_styles['background']['color'] ) ) {
|
133 |
+
$styles .= 'background-color:' . $theme_styles['background']['color'] . ';';
|
134 |
+
}
|
135 |
+
if ( ! empty( $theme_styles['background']['border'] ) ) {
|
136 |
+
$styles .= 'border-color:' . $theme_styles['background']['border'] . ';';
|
137 |
+
}
|
138 |
+
|
139 |
+
$styles .= '}';
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( ! empty( $theme_styles['label'] ) ) {
|
143 |
+
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-label {';
|
144 |
+
|
145 |
+
if ( ! empty( $theme_styles['label']['color'] ) ) {
|
146 |
+
$styles .= 'color:' . $theme_styles['label']['color'] . ';';
|
147 |
+
}
|
148 |
+
|
149 |
+
if ( ! empty( $theme_styles['label']['background'] ) ) {
|
150 |
+
$styles .= 'background-color:' . $theme_styles['label']['background'] . ';';
|
151 |
+
}
|
152 |
+
|
153 |
+
$styles .= '}';
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( ! empty( $theme_styles['title'] ) ) {
|
157 |
+
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-title {';
|
158 |
+
|
159 |
+
if ( ! empty( $theme_styles['title']['color'] ) ) {
|
160 |
+
$styles .= 'color:' . $theme_styles['title']['color'] . ';';
|
161 |
+
}
|
162 |
+
if ( ! empty( $theme_styles['title']['size'] ) ) {
|
163 |
+
$styles .= 'font-size:' . $theme_styles['title']['size'] . 'px;';
|
164 |
+
}
|
165 |
+
|
166 |
+
$styles .= '}';
|
167 |
+
}
|
168 |
+
|
169 |
+
if ( ! empty( $theme_styles['border'] ) ) {
|
170 |
+
$styles .= '.exactmetrics-inline-popular-posts.exactmetrics-popular-posts-styled.exactmetrics-inline-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-border {';
|
171 |
+
|
172 |
+
if ( ! empty( $theme_styles['border']['color'] ) ) {
|
173 |
+
$styles .= 'border-color:' . $theme_styles['border']['color'] . ';';
|
174 |
+
}
|
175 |
+
|
176 |
+
$styles .= '}';
|
177 |
+
}
|
178 |
+
}
|
179 |
+
|
180 |
+
return $styles;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Check if we should attempt to automatically insert the inline widget.
|
185 |
+
*/
|
186 |
+
public function maybe_auto_insert() {
|
187 |
+
|
188 |
+
$post_types = $this->post_types;
|
189 |
+
if ( ! empty( $post_types ) && is_singular( $post_types ) && 'automatic' === $this->placement ) {
|
190 |
+
add_filter( 'the_content', array( $this, 'add_inline_posts_to_content' ) );
|
191 |
+
}
|
192 |
+
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Insert the widget in the content.
|
197 |
+
*
|
198 |
+
* @param string $content The post content.
|
199 |
+
*
|
200 |
+
* @return string
|
201 |
+
*/
|
202 |
+
public function add_inline_posts_to_content(
|
203 |
+
$content
|
204 |
+
) {
|
205 |
+
|
206 |
+
if ( $this->is_post_excluded() ) {
|
207 |
+
return $content;
|
208 |
+
}
|
209 |
+
|
210 |
+
$words_count = str_word_count( $content );
|
211 |
+
$after_count = intval( $this->after_count );
|
212 |
+
|
213 |
+
// Insert only if there are more words then the insert after value.
|
214 |
+
if ( $words_count > $after_count ) {
|
215 |
+
|
216 |
+
$words = explode( ' ', $content );
|
217 |
+
$count = 0;
|
218 |
+
|
219 |
+
foreach ( $words as $index => $word ) {
|
220 |
+
$count ++;
|
221 |
+
if ( $count > $after_count ) {
|
222 |
+
$p_index = strpos( $word, '</p>' );
|
223 |
+
// Make sure the paragraph tag is not wrapped in another element like a blockquote.
|
224 |
+
if ( false !== $p_index && false === strpos( $word, '</p></' ) ) {
|
225 |
+
$words[ $index ] = substr_replace( $word, $this->shortcode_output( array() ), $p_index + 4, 0 );
|
226 |
+
$this->posts = array();
|
227 |
+
break;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
}
|
231 |
+
|
232 |
+
$content = implode( ' ', $words );
|
233 |
+
|
234 |
+
}
|
235 |
+
|
236 |
+
return $content;
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Check if the selected theme is available with the current license to avoid showing a theme not available.
|
241 |
+
* Returns the default 'alpha' theme if not available.
|
242 |
+
*
|
243 |
+
* @param string $theme Theme slug for which we are checking.
|
244 |
+
*
|
245 |
+
* @return string
|
246 |
+
*/
|
247 |
+
public function is_theme_available( $theme ) {
|
248 |
+
|
249 |
+
$theme_props = $this->get_theme_props( $theme )->get_theme();
|
250 |
+
|
251 |
+
if ( ! empty( $theme_props['level'] ) && 'lite' === $theme_props['level'] ) {
|
252 |
+
return $theme;
|
253 |
+
}
|
254 |
+
|
255 |
+
return 'alpha';
|
256 |
+
|
257 |
+
}
|
258 |
+
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Get the current class in a function.
|
263 |
+
*
|
264 |
+
* @return ExactMetrics_Popular_Posts_Inline Instance of the current class.
|
265 |
+
*/
|
266 |
+
function ExactMetrics_Popular_Posts_Inline() {
|
267 |
+
return ExactMetrics_Popular_Posts_Inline::get_instance();
|
268 |
+
}
|
269 |
+
|
270 |
+
ExactMetrics_Popular_Posts_Inline();
|
lite/includes/popular-posts/class-popular-posts-widget-sidebar.php
CHANGED
@@ -1,425 +1,425 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Class used to add the Popular Posts widget to the Appearance > Widget area.
|
4 |
-
*/
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class ExactMetrics_Popular_Posts_Widget_Sidebar
|
8 |
-
*/
|
9 |
-
class ExactMetrics_Popular_Posts_Widget_Sidebar extends WP_Widget {
|
10 |
-
/**
|
11 |
-
* Hold widget settings defaults, populated in constructor.
|
12 |
-
*
|
13 |
-
* @since 7.12.0
|
14 |
-
*
|
15 |
-
* @var array
|
16 |
-
*/
|
17 |
-
protected $defaults;
|
18 |
-
/**
|
19 |
-
* Hold widget options that are theme specific.
|
20 |
-
*
|
21 |
-
* @since 7.12.0
|
22 |
-
*
|
23 |
-
* @var array
|
24 |
-
*/
|
25 |
-
protected $conditional_options;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Constructor
|
29 |
-
*
|
30 |
-
* @since 7.12.0
|
31 |
-
*/
|
32 |
-
public function __construct() {
|
33 |
-
|
34 |
-
// Widget defaults.
|
35 |
-
$this->defaults = array(
|
36 |
-
'title' => '',
|
37 |
-
'display_title' => 'on',
|
38 |
-
'post_count' => 5,
|
39 |
-
'theme' => 'alpha',
|
40 |
-
'title_color' => '#393F4C',
|
41 |
-
'title_size' => 12,
|
42 |
-
'label_color' => '#EB5757',
|
43 |
-
'label_text' => 'Trending',
|
44 |
-
'meta_color' => '#99A1B3',
|
45 |
-
'meta_size' => '12',
|
46 |
-
'meta_author' => 'on',
|
47 |
-
'meta_date' => 'on',
|
48 |
-
'meta_comments' => 'on',
|
49 |
-
'background_color' => '#F0F2F4',
|
50 |
-
'border_color' => '#D3D7DE',
|
51 |
-
'columns' => '1',
|
52 |
-
);
|
53 |
-
|
54 |
-
$this->conditional_options = array(
|
55 |
-
'title_color' => array( 'title', 'color' ),
|
56 |
-
'title_size' => array( 'title', 'size' ),
|
57 |
-
'label_color' => array( 'label', 'color' ),
|
58 |
-
'label_text' => array( 'label', 'text' ),
|
59 |
-
'background_color' => array( 'background', 'color' ),
|
60 |
-
'background_border' => array( 'background', 'border' ),
|
61 |
-
'meta_color' => array( 'meta', 'color' ),
|
62 |
-
'meta_size' => array( 'meta', 'size' ),
|
63 |
-
'meta_author' => array( 'meta', 'author' ),
|
64 |
-
'meta_date' => array( 'meta', 'date' ),
|
65 |
-
'meta_comments' => array( 'meta', 'comments' ),
|
66 |
-
'comments_color' => array( 'comments', 'color' ),
|
67 |
-
);
|
68 |
-
|
69 |
-
// Widget Slug.
|
70 |
-
$widget_slug = 'exactmetrics-popular-posts-widget';
|
71 |
-
|
72 |
-
// Widget basics.
|
73 |
-
$widget_ops = array(
|
74 |
-
'classname' => $widget_slug,
|
75 |
-
'description' => esc_html_x( 'Display popular posts.', 'Widget', 'google-analytics-dashboard-for-wp' ),
|
76 |
-
);
|
77 |
-
|
78 |
-
// Widget controls.
|
79 |
-
$control_ops = array(
|
80 |
-
'id_base' => $widget_slug,
|
81 |
-
);
|
82 |
-
|
83 |
-
$this->add_scripts();
|
84 |
-
|
85 |
-
// Load widget.
|
86 |
-
parent::__construct( $widget_slug, esc_html_x( 'Popular Posts - ExactMetrics', 'Widget', 'google-analytics-dashboard-for-wp' ), $widget_ops, $control_ops );
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Output the HTML for this widget.
|
91 |
-
*
|
92 |
-
* @param array $args An array of standard parameters for widgets in this theme.
|
93 |
-
* @param array $instance An array of settings for this widget instance.
|
94 |
-
*
|
95 |
-
* @since 7.12.0
|
96 |
-
*
|
97 |
-
*/
|
98 |
-
public function widget( $args, $instance ) {
|
99 |
-
|
100 |
-
echo $args['before_widget'];
|
101 |
-
|
102 |
-
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
|
103 |
-
|
104 |
-
if ( $instance['display_title'] && ! empty( $instance['title'] ) ) {
|
105 |
-
echo $args['before_title'];
|
106 |
-
echo wp_kses_post( $title );
|
107 |
-
echo $args['after_title'];
|
108 |
-
}
|
109 |
-
|
110 |
-
$atts = array(
|
111 |
-
'theme' => $instance['theme'],
|
112 |
-
'post_count' => $instance['post_count'],
|
113 |
-
'columns' => 1, // Sidebar is not wide so we always use the 1 column layout.
|
114 |
-
'widget_title' => false, // Override this in favor of sidebar-specific markup above.
|
115 |
-
);
|
116 |
-
|
117 |
-
foreach ( $this->conditional_options as $key => $default ) {
|
118 |
-
if ( ! empty( $instance[ $key ] ) ) {
|
119 |
-
$atts[ $key ] = $instance[ $key ];
|
120 |
-
}
|
121 |
-
}
|
122 |
-
|
123 |
-
echo ExactMetrics_Popular_Posts_Widget()->shortcode_output( $atts );
|
124 |
-
|
125 |
-
echo $args['after_widget'];
|
126 |
-
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* Deal with the settings when they are saved by the admin. Here is
|
131 |
-
* where any validation should be dealt with.
|
132 |
-
*
|
133 |
-
* @param array $new_instance An array of new settings as submitted by the admin.
|
134 |
-
* @param array $old_instance An array of the previous settings.
|
135 |
-
*
|
136 |
-
* @return array The validated and (if necessary) amended settings
|
137 |
-
* @since 7.12.0
|
138 |
-
*
|
139 |
-
*/
|
140 |
-
public function update( $new_instance, $old_instance ) {
|
141 |
-
|
142 |
-
$new_instance['title'] = wp_strip_all_tags( $new_instance['title'] );
|
143 |
-
$new_instance['theme'] = wp_strip_all_tags( $new_instance['theme'] );
|
144 |
-
$new_instance['display_title'] = isset( $new_instance['display_title'] ) ? wp_strip_all_tags( $new_instance['display_title'] ) : '';
|
145 |
-
$new_instance['post_count'] = absint( $new_instance['post_count'] );
|
146 |
-
|
147 |
-
// Theme-dependant options.
|
148 |
-
$themes = new ExactMetrics_Popular_Posts_Themes( 'widget', ! empty( $old_instance['theme'] ) ? $old_instance['theme'] : '' );
|
149 |
-
$theme = $themes->get_theme();
|
150 |
-
|
151 |
-
foreach ( $this->conditional_options as $key => $obj ) {
|
152 |
-
$new_instance = $this->maybe_remove_option( ! empty( $theme['styles'][ $obj[0] ][ $obj[1] ] ), $key, $new_instance );
|
153 |
-
}
|
154 |
-
|
155 |
-
return $new_instance;
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* Process dynamic and checkbox values so they are stored correctly and specific to the current theme.
|
160 |
-
*
|
161 |
-
* @param bool $is_used A check if this property is used in the currently selected theme.
|
162 |
-
* @param string $key The key of the property we're checking.
|
163 |
-
* @param array $instance The current widget instance, new instance.
|
164 |
-
*
|
165 |
-
* @return mixed
|
166 |
-
*/
|
167 |
-
public function maybe_remove_option( $is_used, $key, $instance ) {
|
168 |
-
|
169 |
-
$checkboxes = array(
|
170 |
-
'meta_author',
|
171 |
-
'meta_date',
|
172 |
-
'meta_comments',
|
173 |
-
);
|
174 |
-
|
175 |
-
if ( $is_used && ! isset( $instance[ $key ] ) && in_array( $key, $checkboxes ) ) {
|
176 |
-
$instance[ $key ] = 'off';
|
177 |
-
} elseif ( ! $is_used && isset( $instance[ $key ] ) ) {
|
178 |
-
unset( $instance[ $key ] );
|
179 |
-
} elseif ( $is_used && isset( $instance[ $key ] ) ) {
|
180 |
-
$instance[ $key ] = wp_strip_all_tags( $instance[ $key ] );
|
181 |
-
}
|
182 |
-
|
183 |
-
return $instance;
|
184 |
-
}
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Display the form for this widget on the Widgets page of the WP Admin area.
|
188 |
-
*
|
189 |
-
* @param array $instance An array of the current settings for this widget.
|
190 |
-
*
|
191 |
-
* @since 7.12.0
|
192 |
-
*/
|
193 |
-
public function form( $instance ) {
|
194 |
-
|
195 |
-
// Merge with defaults but use theme settings from Vue as defaults.
|
196 |
-
$theme_name = empty( $instance['theme'] ) ? $this->defaults['theme'] : $instance['theme'];
|
197 |
-
$themes = new ExactMetrics_Popular_Posts_Themes( 'widget', $theme_name );
|
198 |
-
$theme = $themes->get_theme();
|
199 |
-
$this->prepare_defaults_from_theme( $theme );
|
200 |
-
|
201 |
-
$instance = wp_parse_args( (array) $instance, $this->defaults );
|
202 |
-
|
203 |
-
$title_font_sizes = apply_filters( 'exactmetrics_popular_posts_widget_title_sizes', range( 10, 35 ) );
|
204 |
-
|
205 |
-
$this->text_input( 'title', _x( 'Widget Title:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
206 |
-
|
207 |
-
$categories = array(
|
208 |
-
array(
|
209 |
-
'name' => 'News',
|
210 |
-
'value' => '0',
|
211 |
-
),
|
212 |
-
array(
|
213 |
-
'name' => 'Technology',
|
214 |
-
'value' => '1',
|
215 |
-
),
|
216 |
-
);
|
217 |
-
?>
|
218 |
-
<p>
|
219 |
-
<input type="checkbox"
|
220 |
-
id="<?php echo esc_attr( $this->get_field_id( 'display_title' ) ); ?>"
|
221 |
-
name="<?php echo esc_attr( $this->get_field_name( 'display_title' ) ); ?>"
|
222 |
-
value="on" <?php checked( $instance['display_title'], 'on' ); ?> />
|
223 |
-
<label for="<?php echo esc_attr( $this->get_field_id( 'display_title' ) ); ?>">
|
224 |
-
<?php echo esc_html( _x( 'Display Widget Title', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
225 |
-
</label>
|
226 |
-
</p>
|
227 |
-
<p>
|
228 |
-
<label for="<?php echo esc_attr( $this->get_field_id( 'post_count' ) ); ?>">
|
229 |
-
<?php echo esc_html( _x( 'Number of posts to display:', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
230 |
-
</label>
|
231 |
-
<select id="<?php echo esc_attr( $this->get_field_id( 'post_count' ) ); ?>"
|
232 |
-
name="<?php echo esc_attr( $this->get_field_name( 'post_count' ) ); ?>">
|
233 |
-
<option value="5" <?php selected( $instance['post_count'], 5 ); ?>>5</option>
|
234 |
-
<option value="10" <?php selected( $instance['post_count'], 10 ); ?>>10</option>
|
235 |
-
</select>
|
236 |
-
</p>
|
237 |
-
<p>
|
238 |
-
<label for="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>">
|
239 |
-
<?php echo esc_html( _x( 'Theme:', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
240 |
-
</label>
|
241 |
-
<select id="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>"
|
242 |
-
class="widefat exactmetrics-save-on-change"
|
243 |
-
name="<?php echo esc_attr( $this->get_field_name( 'theme' ) ); ?>">
|
244 |
-
<?php foreach ( $themes->themes as $key => $details ) {
|
245 |
-
if ( 'lite' !== $details['level'] ) {
|
246 |
-
continue;
|
247 |
-
}
|
248 |
-
?>
|
249 |
-
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $instance['theme'], $key ); ?>>
|
250 |
-
<?php echo esc_html( ucfirst( $key ) ); ?>
|
251 |
-
</option>
|
252 |
-
<?php } ?>
|
253 |
-
</select>
|
254 |
-
</p>
|
255 |
-
<div class="exactmetrics-widget-theme-preview">
|
256 |
-
<span class="exactmetrics-widget-theme-preview-label">
|
257 |
-
<?php esc_html_e( 'Theme Preview', 'google-analytics-dashboard-for-wp' ); ?>
|
258 |
-
</span>
|
259 |
-
<div class="exactmetrics-widget-theme-preview-icon exactmetrics-widget-theme-preview-icon-<?php echo esc_attr( $instance['theme'] ); ?>"></div>
|
260 |
-
</div>
|
261 |
-
<?php if ( ! empty( $theme['styles']['title']['color'] ) ) {
|
262 |
-
$this->color_input( 'title_color', _x( 'Title Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
263 |
-
?>
|
264 |
-
<?php
|
265 |
-
}
|
266 |
-
if ( ! empty( $theme['styles']['title']['size'] ) ) {
|
267 |
-
$this->size_input( 'title_size', _x( 'Title Font Size:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance, $title_font_sizes );
|
268 |
-
}
|
269 |
-
if ( ! empty( $theme['styles']['label']['color'] ) ) {
|
270 |
-
$this->color_input( 'label_color', _x( 'Label Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
271 |
-
}
|
272 |
-
if ( ! empty( $theme['styles']['label']['editable'] ) && ! empty( $theme['styles']['label']['text'] ) ) {
|
273 |
-
$this->text_input( 'label_text', _x( 'Label Text:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
274 |
-
}
|
275 |
-
if ( ! empty( $theme['styles']['background']['border'] ) ) {
|
276 |
-
$this->color_input( 'background_border', _x( 'Border Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
277 |
-
}
|
278 |
-
if ( ! empty( $theme['styles']['background']['color'] ) ) {
|
279 |
-
$this->color_input( 'background_color', _x( 'Background Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
280 |
-
}
|
281 |
-
if ( ! empty( $theme['styles']['comments']['color'] ) ) {
|
282 |
-
$this->color_input( 'comments_color', _x( 'Comments Count Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
283 |
-
}
|
284 |
-
?>
|
285 |
-
<p>
|
286 |
-
|
287 |
-
<label class="exactmetrics-label-block">
|
288 |
-
<?php echo esc_html( _x( 'Only Show Posts from These Categories:', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
289 |
-
<span class="exactmetrics-pro-pill">PRO</span>
|
290 |
-
</label>
|
291 |
-
<div class="select300 select300-container select300-container--default select300-container--disabled select300-container--focus"
|
292 |
-
dir="ltr" data-select300-id="2" style="width: auto;">
|
293 |
-
<div class="selection">
|
294 |
-
<div class="select300-selection select300-selection--multiple">
|
295 |
-
<ul class="select300-selection__rendered">
|
296 |
-
<li class="select300-selection__choice" title="News" data-select300-id="5">
|
297 |
-
<span class="select300-selection__choice__remove" role="presentation">×</span>News
|
298 |
-
</li>
|
299 |
-
<li class="select300-selection__choice" title="Technology" data-select300-id="6">
|
300 |
-
<span class="select300-selection__choice__remove" role="presentation">×</span>Technology
|
301 |
-
</li>
|
302 |
-
</ul>
|
303 |
-
</div>
|
304 |
-
</div>
|
305 |
-
</div>
|
306 |
-
</p>
|
307 |
-
<?php
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* Colorpicker input element.
|
312 |
-
*
|
313 |
-
* @param string $name Name of the input, for saving/loading.
|
314 |
-
* @param string $label Label of the element.
|
315 |
-
* @param array $instance The current widget instance.
|
316 |
-
*/
|
317 |
-
public function color_input( $name, $label, $instance ) {
|
318 |
-
?>
|
319 |
-
<p>
|
320 |
-
<label class="exactmetrics-label-block"
|
321 |
-
for="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>">
|
322 |
-
<?php echo esc_html( $label ); ?>
|
323 |
-
</label>
|
324 |
-
<input type="text"
|
325 |
-
id="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>"
|
326 |
-
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>"
|
327 |
-
value="<?php echo esc_attr( $instance[ $name ] ); ?>"
|
328 |
-
class="widefat exactmetrics-color-field"/>
|
329 |
-
</p>
|
330 |
-
<?php
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Regular text input.
|
335 |
-
*
|
336 |
-
* @param string $name Name of the input, for saving/loading.
|
337 |
-
* @param string $label Label of the element.
|
338 |
-
* @param array $instance The current widget instance.
|
339 |
-
*/
|
340 |
-
public function text_input( $name, $label, $instance ) {
|
341 |
-
?>
|
342 |
-
<p>
|
343 |
-
<label for="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>">
|
344 |
-
<?php echo esc_html( $label ); ?>
|
345 |
-
</label>
|
346 |
-
<input type="text"
|
347 |
-
id="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>"
|
348 |
-
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>"
|
349 |
-
value="<?php echo esc_attr( $instance[ $name ] ); ?>" class="widefat"/>
|
350 |
-
</p>
|
351 |
-
<?php
|
352 |
-
}
|
353 |
-
|
354 |
-
/**
|
355 |
-
* Size input - used for font size inputs.
|
356 |
-
*
|
357 |
-
* @param string $name Name of the input, for saving/loading.
|
358 |
-
* @param string $label Label of the element.
|
359 |
-
* @param array $instance The current widget instance.
|
360 |
-
* @param array $range The options available to select.
|
361 |
-
*/
|
362 |
-
public function size_input( $name, $label, $instance, $range = array() ) {
|
363 |
-
?>
|
364 |
-
<p>
|
365 |
-
<label for="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>">
|
366 |
-
<?php echo esc_html( $label ); ?>
|
367 |
-
</label>
|
368 |
-
<select id="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>"
|
369 |
-
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>" class="widefat">
|
370 |
-
<?php foreach ( $range as $font_size ) { ?>
|
371 |
-
<option value="<?php echo absint( $font_size ); ?>" <?php selected( $instance[ $name ], $font_size ); ?>><?php printf( esc_html_x( '%dpx', 'google-analytics-dashboard-for-wp' ), $font_size ); ?></option>
|
372 |
-
<?php } ?>
|
373 |
-
</select>
|
374 |
-
</p>
|
375 |
-
<?php
|
376 |
-
}
|
377 |
-
|
378 |
-
/**
|
379 |
-
* Prepare theme specific options.
|
380 |
-
*
|
381 |
-
* @param array $theme The theme options.
|
382 |
-
*/
|
383 |
-
public function prepare_defaults_from_theme( $theme ) {
|
384 |
-
foreach ( $this->conditional_options as $key => $obj ) {
|
385 |
-
if ( ! empty( $theme['styles'][ $obj[0] ][ $obj[1] ] ) ) {
|
386 |
-
$this->defaults[ $key ] = $theme['styles'][ $obj[0] ][ $obj[1] ];
|
387 |
-
}
|
388 |
-
}
|
389 |
-
}
|
390 |
-
|
391 |
-
/**
|
392 |
-
* Load specific widget scripts in the admin.
|
393 |
-
*/
|
394 |
-
public function add_scripts() {
|
395 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'load_widget_scripts' ) );
|
396 |
-
}
|
397 |
-
|
398 |
-
/**
|
399 |
-
* Load admin-specific widget scripts.
|
400 |
-
*/
|
401 |
-
public function load_widget_scripts() {
|
402 |
-
|
403 |
-
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
|
404 |
-
|
405 |
-
if ( ! isset( $screen->id ) || 'widgets' !== $screen->id ) {
|
406 |
-
return;
|
407 |
-
}
|
408 |
-
|
409 |
-
|
410 |
-
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
411 |
-
wp_enqueue_style( 'exactmetrics-admin-widget-setting-styles', plugins_url( 'assets/css/admin-widget-settings' . $suffix . '.css', EXACTMETRICS_PLUGIN_FILE ), array(
|
412 |
-
'wp-color-picker',
|
413 |
-
), exactmetrics_get_asset_version() );
|
414 |
-
|
415 |
-
wp_register_script( 'exactmetrics-admin-widget-settings', plugins_url( 'assets/js/admin-widget-settings' . $suffix . '.js', EXACTMETRICS_PLUGIN_FILE ), array(
|
416 |
-
'jquery',
|
417 |
-
'wp-color-picker',
|
418 |
-
), exactmetrics_get_asset_version(), true );
|
419 |
-
wp_enqueue_script( 'exactmetrics-admin-widget-settings' );
|
420 |
-
|
421 |
-
wp_localize_script( 'exactmetrics-admin-widget-settings', 'exactmetrics_pp', array(
|
422 |
-
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
423 |
-
) );
|
424 |
-
}
|
425 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used to add the Popular Posts widget to the Appearance > Widget area.
|
4 |
+
*/
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class ExactMetrics_Popular_Posts_Widget_Sidebar
|
8 |
+
*/
|
9 |
+
class ExactMetrics_Popular_Posts_Widget_Sidebar extends WP_Widget {
|
10 |
+
/**
|
11 |
+
* Hold widget settings defaults, populated in constructor.
|
12 |
+
*
|
13 |
+
* @since 7.12.0
|
14 |
+
*
|
15 |
+
* @var array
|
16 |
+
*/
|
17 |
+
protected $defaults;
|
18 |
+
/**
|
19 |
+
* Hold widget options that are theme specific.
|
20 |
+
*
|
21 |
+
* @since 7.12.0
|
22 |
+
*
|
23 |
+
* @var array
|
24 |
+
*/
|
25 |
+
protected $conditional_options;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Constructor
|
29 |
+
*
|
30 |
+
* @since 7.12.0
|
31 |
+
*/
|
32 |
+
public function __construct() {
|
33 |
+
|
34 |
+
// Widget defaults.
|
35 |
+
$this->defaults = array(
|
36 |
+
'title' => '',
|
37 |
+
'display_title' => 'on',
|
38 |
+
'post_count' => 5,
|
39 |
+
'theme' => 'alpha',
|
40 |
+
'title_color' => '#393F4C',
|
41 |
+
'title_size' => 12,
|
42 |
+
'label_color' => '#EB5757',
|
43 |
+
'label_text' => 'Trending',
|
44 |
+
'meta_color' => '#99A1B3',
|
45 |
+
'meta_size' => '12',
|
46 |
+
'meta_author' => 'on',
|
47 |
+
'meta_date' => 'on',
|
48 |
+
'meta_comments' => 'on',
|
49 |
+
'background_color' => '#F0F2F4',
|
50 |
+
'border_color' => '#D3D7DE',
|
51 |
+
'columns' => '1',
|
52 |
+
);
|
53 |
+
|
54 |
+
$this->conditional_options = array(
|
55 |
+
'title_color' => array( 'title', 'color' ),
|
56 |
+
'title_size' => array( 'title', 'size' ),
|
57 |
+
'label_color' => array( 'label', 'color' ),
|
58 |
+
'label_text' => array( 'label', 'text' ),
|
59 |
+
'background_color' => array( 'background', 'color' ),
|
60 |
+
'background_border' => array( 'background', 'border' ),
|
61 |
+
'meta_color' => array( 'meta', 'color' ),
|
62 |
+
'meta_size' => array( 'meta', 'size' ),
|
63 |
+
'meta_author' => array( 'meta', 'author' ),
|
64 |
+
'meta_date' => array( 'meta', 'date' ),
|
65 |
+
'meta_comments' => array( 'meta', 'comments' ),
|
66 |
+
'comments_color' => array( 'comments', 'color' ),
|
67 |
+
);
|
68 |
+
|
69 |
+
// Widget Slug.
|
70 |
+
$widget_slug = 'exactmetrics-popular-posts-widget';
|
71 |
+
|
72 |
+
// Widget basics.
|
73 |
+
$widget_ops = array(
|
74 |
+
'classname' => $widget_slug,
|
75 |
+
'description' => esc_html_x( 'Display popular posts.', 'Widget', 'google-analytics-dashboard-for-wp' ),
|
76 |
+
);
|
77 |
+
|
78 |
+
// Widget controls.
|
79 |
+
$control_ops = array(
|
80 |
+
'id_base' => $widget_slug,
|
81 |
+
);
|
82 |
+
|
83 |
+
$this->add_scripts();
|
84 |
+
|
85 |
+
// Load widget.
|
86 |
+
parent::__construct( $widget_slug, esc_html_x( 'Popular Posts - ExactMetrics', 'Widget', 'google-analytics-dashboard-for-wp' ), $widget_ops, $control_ops );
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Output the HTML for this widget.
|
91 |
+
*
|
92 |
+
* @param array $args An array of standard parameters for widgets in this theme.
|
93 |
+
* @param array $instance An array of settings for this widget instance.
|
94 |
+
*
|
95 |
+
* @since 7.12.0
|
96 |
+
*
|
97 |
+
*/
|
98 |
+
public function widget( $args, $instance ) {
|
99 |
+
|
100 |
+
echo $args['before_widget'];
|
101 |
+
|
102 |
+
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
|
103 |
+
|
104 |
+
if ( $instance['display_title'] && ! empty( $instance['title'] ) ) {
|
105 |
+
echo $args['before_title'];
|
106 |
+
echo wp_kses_post( $title );
|
107 |
+
echo $args['after_title'];
|
108 |
+
}
|
109 |
+
|
110 |
+
$atts = array(
|
111 |
+
'theme' => $instance['theme'],
|
112 |
+
'post_count' => $instance['post_count'],
|
113 |
+
'columns' => 1, // Sidebar is not wide so we always use the 1 column layout.
|
114 |
+
'widget_title' => false, // Override this in favor of sidebar-specific markup above.
|
115 |
+
);
|
116 |
+
|
117 |
+
foreach ( $this->conditional_options as $key => $default ) {
|
118 |
+
if ( ! empty( $instance[ $key ] ) ) {
|
119 |
+
$atts[ $key ] = $instance[ $key ];
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
echo ExactMetrics_Popular_Posts_Widget()->shortcode_output( $atts );
|
124 |
+
|
125 |
+
echo $args['after_widget'];
|
126 |
+
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Deal with the settings when they are saved by the admin. Here is
|
131 |
+
* where any validation should be dealt with.
|
132 |
+
*
|
133 |
+
* @param array $new_instance An array of new settings as submitted by the admin.
|
134 |
+
* @param array $old_instance An array of the previous settings.
|
135 |
+
*
|
136 |
+
* @return array The validated and (if necessary) amended settings
|
137 |
+
* @since 7.12.0
|
138 |
+
*
|
139 |
+
*/
|
140 |
+
public function update( $new_instance, $old_instance ) {
|
141 |
+
|
142 |
+
$new_instance['title'] = wp_strip_all_tags( $new_instance['title'] );
|
143 |
+
$new_instance['theme'] = wp_strip_all_tags( $new_instance['theme'] );
|
144 |
+
$new_instance['display_title'] = isset( $new_instance['display_title'] ) ? wp_strip_all_tags( $new_instance['display_title'] ) : '';
|
145 |
+
$new_instance['post_count'] = absint( $new_instance['post_count'] );
|
146 |
+
|
147 |
+
// Theme-dependant options.
|
148 |
+
$themes = new ExactMetrics_Popular_Posts_Themes( 'widget', ! empty( $old_instance['theme'] ) ? $old_instance['theme'] : '' );
|
149 |
+
$theme = $themes->get_theme();
|
150 |
+
|
151 |
+
foreach ( $this->conditional_options as $key => $obj ) {
|
152 |
+
$new_instance = $this->maybe_remove_option( ! empty( $theme['styles'][ $obj[0] ][ $obj[1] ] ), $key, $new_instance );
|
153 |
+
}
|
154 |
+
|
155 |
+
return $new_instance;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Process dynamic and checkbox values so they are stored correctly and specific to the current theme.
|
160 |
+
*
|
161 |
+
* @param bool $is_used A check if this property is used in the currently selected theme.
|
162 |
+
* @param string $key The key of the property we're checking.
|
163 |
+
* @param array $instance The current widget instance, new instance.
|
164 |
+
*
|
165 |
+
* @return mixed
|
166 |
+
*/
|
167 |
+
public function maybe_remove_option( $is_used, $key, $instance ) {
|
168 |
+
|
169 |
+
$checkboxes = array(
|
170 |
+
'meta_author',
|
171 |
+
'meta_date',
|
172 |
+
'meta_comments',
|
173 |
+
);
|
174 |
+
|
175 |
+
if ( $is_used && ! isset( $instance[ $key ] ) && in_array( $key, $checkboxes ) ) {
|
176 |
+
$instance[ $key ] = 'off';
|
177 |
+
} elseif ( ! $is_used && isset( $instance[ $key ] ) ) {
|
178 |
+
unset( $instance[ $key ] );
|
179 |
+
} elseif ( $is_used && isset( $instance[ $key ] ) ) {
|
180 |
+
$instance[ $key ] = wp_strip_all_tags( $instance[ $key ] );
|
181 |
+
}
|
182 |
+
|
183 |
+
return $instance;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Display the form for this widget on the Widgets page of the WP Admin area.
|
188 |
+
*
|
189 |
+
* @param array $instance An array of the current settings for this widget.
|
190 |
+
*
|
191 |
+
* @since 7.12.0
|
192 |
+
*/
|
193 |
+
public function form( $instance ) {
|
194 |
+
|
195 |
+
// Merge with defaults but use theme settings from Vue as defaults.
|
196 |
+
$theme_name = empty( $instance['theme'] ) ? $this->defaults['theme'] : $instance['theme'];
|
197 |
+
$themes = new ExactMetrics_Popular_Posts_Themes( 'widget', $theme_name );
|
198 |
+
$theme = $themes->get_theme();
|
199 |
+
$this->prepare_defaults_from_theme( $theme );
|
200 |
+
|
201 |
+
$instance = wp_parse_args( (array) $instance, $this->defaults );
|
202 |
+
|
203 |
+
$title_font_sizes = apply_filters( 'exactmetrics_popular_posts_widget_title_sizes', range( 10, 35 ) );
|
204 |
+
|
205 |
+
$this->text_input( 'title', _x( 'Widget Title:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
206 |
+
|
207 |
+
$categories = array(
|
208 |
+
array(
|
209 |
+
'name' => 'News',
|
210 |
+
'value' => '0',
|
211 |
+
),
|
212 |
+
array(
|
213 |
+
'name' => 'Technology',
|
214 |
+
'value' => '1',
|
215 |
+
),
|
216 |
+
);
|
217 |
+
?>
|
218 |
+
<p>
|
219 |
+
<input type="checkbox"
|
220 |
+
id="<?php echo esc_attr( $this->get_field_id( 'display_title' ) ); ?>"
|
221 |
+
name="<?php echo esc_attr( $this->get_field_name( 'display_title' ) ); ?>"
|
222 |
+
value="on" <?php checked( $instance['display_title'], 'on' ); ?> />
|
223 |
+
<label for="<?php echo esc_attr( $this->get_field_id( 'display_title' ) ); ?>">
|
224 |
+
<?php echo esc_html( _x( 'Display Widget Title', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
225 |
+
</label>
|
226 |
+
</p>
|
227 |
+
<p>
|
228 |
+
<label for="<?php echo esc_attr( $this->get_field_id( 'post_count' ) ); ?>">
|
229 |
+
<?php echo esc_html( _x( 'Number of posts to display:', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
230 |
+
</label>
|
231 |
+
<select id="<?php echo esc_attr( $this->get_field_id( 'post_count' ) ); ?>"
|
232 |
+
name="<?php echo esc_attr( $this->get_field_name( 'post_count' ) ); ?>">
|
233 |
+
<option value="5" <?php selected( $instance['post_count'], 5 ); ?>>5</option>
|
234 |
+
<option value="10" <?php selected( $instance['post_count'], 10 ); ?>>10</option>
|
235 |
+
</select>
|
236 |
+
</p>
|
237 |
+
<p>
|
238 |
+
<label for="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>">
|
239 |
+
<?php echo esc_html( _x( 'Theme:', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
240 |
+
</label>
|
241 |
+
<select id="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>"
|
242 |
+
class="widefat exactmetrics-save-on-change"
|
243 |
+
name="<?php echo esc_attr( $this->get_field_name( 'theme' ) ); ?>">
|
244 |
+
<?php foreach ( $themes->themes as $key => $details ) {
|
245 |
+
if ( 'lite' !== $details['level'] ) {
|
246 |
+
continue;
|
247 |
+
}
|
248 |
+
?>
|
249 |
+
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $instance['theme'], $key ); ?>>
|
250 |
+
<?php echo esc_html( ucfirst( $key ) ); ?>
|
251 |
+
</option>
|
252 |
+
<?php } ?>
|
253 |
+
</select>
|
254 |
+
</p>
|
255 |
+
<div class="exactmetrics-widget-theme-preview">
|
256 |
+
<span class="exactmetrics-widget-theme-preview-label">
|
257 |
+
<?php esc_html_e( 'Theme Preview', 'google-analytics-dashboard-for-wp' ); ?>
|
258 |
+
</span>
|
259 |
+
<div class="exactmetrics-widget-theme-preview-icon exactmetrics-widget-theme-preview-icon-<?php echo esc_attr( $instance['theme'] ); ?>"></div>
|
260 |
+
</div>
|
261 |
+
<?php if ( ! empty( $theme['styles']['title']['color'] ) ) {
|
262 |
+
$this->color_input( 'title_color', _x( 'Title Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
263 |
+
?>
|
264 |
+
<?php
|
265 |
+
}
|
266 |
+
if ( ! empty( $theme['styles']['title']['size'] ) ) {
|
267 |
+
$this->size_input( 'title_size', _x( 'Title Font Size:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance, $title_font_sizes );
|
268 |
+
}
|
269 |
+
if ( ! empty( $theme['styles']['label']['color'] ) ) {
|
270 |
+
$this->color_input( 'label_color', _x( 'Label Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
271 |
+
}
|
272 |
+
if ( ! empty( $theme['styles']['label']['editable'] ) && ! empty( $theme['styles']['label']['text'] ) ) {
|
273 |
+
$this->text_input( 'label_text', _x( 'Label Text:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
274 |
+
}
|
275 |
+
if ( ! empty( $theme['styles']['background']['border'] ) ) {
|
276 |
+
$this->color_input( 'background_border', _x( 'Border Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
277 |
+
}
|
278 |
+
if ( ! empty( $theme['styles']['background']['color'] ) ) {
|
279 |
+
$this->color_input( 'background_color', _x( 'Background Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
280 |
+
}
|
281 |
+
if ( ! empty( $theme['styles']['comments']['color'] ) ) {
|
282 |
+
$this->color_input( 'comments_color', _x( 'Comments Count Color:', 'Widget', 'google-analytics-dashboard-for-wp' ), $instance );
|
283 |
+
}
|
284 |
+
?>
|
285 |
+
<p>
|
286 |
+
|
287 |
+
<label class="exactmetrics-label-block">
|
288 |
+
<?php echo esc_html( _x( 'Only Show Posts from These Categories:', 'Widget', 'google-analytics-dashboard-for-wp' ) ); ?>
|
289 |
+
<span class="exactmetrics-pro-pill">PRO</span>
|
290 |
+
</label>
|
291 |
+
<div class="select300 select300-container select300-container--default select300-container--disabled select300-container--focus"
|
292 |
+
dir="ltr" data-select300-id="2" style="width: auto;">
|
293 |
+
<div class="selection">
|
294 |
+
<div class="select300-selection select300-selection--multiple">
|
295 |
+
<ul class="select300-selection__rendered">
|
296 |
+
<li class="select300-selection__choice" title="News" data-select300-id="5">
|
297 |
+
<span class="select300-selection__choice__remove" role="presentation">×</span>News
|
298 |
+
</li>
|
299 |
+
<li class="select300-selection__choice" title="Technology" data-select300-id="6">
|
300 |
+
<span class="select300-selection__choice__remove" role="presentation">×</span>Technology
|
301 |
+
</li>
|
302 |
+
</ul>
|
303 |
+
</div>
|
304 |
+
</div>
|
305 |
+
</div>
|
306 |
+
</p>
|
307 |
+
<?php
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Colorpicker input element.
|
312 |
+
*
|
313 |
+
* @param string $name Name of the input, for saving/loading.
|
314 |
+
* @param string $label Label of the element.
|
315 |
+
* @param array $instance The current widget instance.
|
316 |
+
*/
|
317 |
+
public function color_input( $name, $label, $instance ) {
|
318 |
+
?>
|
319 |
+
<p>
|
320 |
+
<label class="exactmetrics-label-block"
|
321 |
+
for="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>">
|
322 |
+
<?php echo esc_html( $label ); ?>
|
323 |
+
</label>
|
324 |
+
<input type="text"
|
325 |
+
id="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>"
|
326 |
+
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>"
|
327 |
+
value="<?php echo esc_attr( $instance[ $name ] ); ?>"
|
328 |
+
class="widefat exactmetrics-color-field"/>
|
329 |
+
</p>
|
330 |
+
<?php
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Regular text input.
|
335 |
+
*
|
336 |
+
* @param string $name Name of the input, for saving/loading.
|
337 |
+
* @param string $label Label of the element.
|
338 |
+
* @param array $instance The current widget instance.
|
339 |
+
*/
|
340 |
+
public function text_input( $name, $label, $instance ) {
|
341 |
+
?>
|
342 |
+
<p>
|
343 |
+
<label for="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>">
|
344 |
+
<?php echo esc_html( $label ); ?>
|
345 |
+
</label>
|
346 |
+
<input type="text"
|
347 |
+
id="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>"
|
348 |
+
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>"
|
349 |
+
value="<?php echo esc_attr( $instance[ $name ] ); ?>" class="widefat"/>
|
350 |
+
</p>
|
351 |
+
<?php
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Size input - used for font size inputs.
|
356 |
+
*
|
357 |
+
* @param string $name Name of the input, for saving/loading.
|
358 |
+
* @param string $label Label of the element.
|
359 |
+
* @param array $instance The current widget instance.
|
360 |
+
* @param array $range The options available to select.
|
361 |
+
*/
|
362 |
+
public function size_input( $name, $label, $instance, $range = array() ) {
|
363 |
+
?>
|
364 |
+
<p>
|
365 |
+
<label for="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>">
|
366 |
+
<?php echo esc_html( $label ); ?>
|
367 |
+
</label>
|
368 |
+
<select id="<?php echo esc_attr( $this->get_field_id( $name ) ); ?>"
|
369 |
+
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>" class="widefat">
|
370 |
+
<?php foreach ( $range as $font_size ) { ?>
|
371 |
+
<option value="<?php echo absint( $font_size ); ?>" <?php selected( $instance[ $name ], $font_size ); ?>><?php printf( esc_html_x( '%dpx', 'google-analytics-dashboard-for-wp' ), $font_size ); ?></option>
|
372 |
+
<?php } ?>
|
373 |
+
</select>
|
374 |
+
</p>
|
375 |
+
<?php
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Prepare theme specific options.
|
380 |
+
*
|
381 |
+
* @param array $theme The theme options.
|
382 |
+
*/
|
383 |
+
public function prepare_defaults_from_theme( $theme ) {
|
384 |
+
foreach ( $this->conditional_options as $key => $obj ) {
|
385 |
+
if ( ! empty( $theme['styles'][ $obj[0] ][ $obj[1] ] ) ) {
|
386 |
+
$this->defaults[ $key ] = $theme['styles'][ $obj[0] ][ $obj[1] ];
|
387 |
+
}
|
388 |
+
}
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Load specific widget scripts in the admin.
|
393 |
+
*/
|
394 |
+
public function add_scripts() {
|
395 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'load_widget_scripts' ) );
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Load admin-specific widget scripts.
|
400 |
+
*/
|
401 |
+
public function load_widget_scripts() {
|
402 |
+
|
403 |
+
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
|
404 |
+
|
405 |
+
if ( ! isset( $screen->id ) || 'widgets' !== $screen->id ) {
|
406 |
+
return;
|
407 |
+
}
|
408 |
+
|
409 |
+
|
410 |
+
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
411 |
+
wp_enqueue_style( 'exactmetrics-admin-widget-setting-styles', plugins_url( 'assets/css/admin-widget-settings' . $suffix . '.css', EXACTMETRICS_PLUGIN_FILE ), array(
|
412 |
+
'wp-color-picker',
|
413 |
+
), exactmetrics_get_asset_version() );
|
414 |
+
|
415 |
+
wp_register_script( 'exactmetrics-admin-widget-settings', plugins_url( 'assets/js/admin-widget-settings' . $suffix . '.js', EXACTMETRICS_PLUGIN_FILE ), array(
|
416 |
+
'jquery',
|
417 |
+
'wp-color-picker',
|
418 |
+
), exactmetrics_get_asset_version(), true );
|
419 |
+
wp_enqueue_script( 'exactmetrics-admin-widget-settings' );
|
420 |
+
|
421 |
+
wp_localize_script( 'exactmetrics-admin-widget-settings', 'exactmetrics_pp', array(
|
422 |
+
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
423 |
+
) );
|
424 |
+
}
|
425 |
+
}
|
lite/includes/popular-posts/class-popular-posts-widget.php
CHANGED
@@ -1,262 +1,262 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Code specific to the widget Popular Posts widget type.
|
4 |
-
*/
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class ExactMetrics_Popular_Posts_Widget
|
8 |
-
*/
|
9 |
-
class ExactMetrics_Popular_Posts_Widget extends ExactMetrics_Popular_Posts {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* The instance type. Used for loading specific settings.
|
13 |
-
*
|
14 |
-
* @var string
|
15 |
-
*/
|
16 |
-
protected $type = 'widget';
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Used to load the setting specific for this class.
|
20 |
-
*
|
21 |
-
* @var string
|
22 |
-
*/
|
23 |
-
protected $settings_key = 'popular_posts_widget';
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Used for registering the shortcode specific to this class.
|
27 |
-
*
|
28 |
-
* @var string
|
29 |
-
*/
|
30 |
-
protected $shortcode_key = 'exactmetrics_popular_posts_widget';
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Widget-specific hooks.
|
34 |
-
*/
|
35 |
-
public function hooks() {
|
36 |
-
parent::hooks();
|
37 |
-
|
38 |
-
add_action( 'wp', array( $this, 'maybe_auto_insert' ) );
|
39 |
-
|
40 |
-
add_action( 'widgets_init', array( $this, 'register_widget' ) );
|
41 |
-
}
|
42 |
-
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Register Popular Posts widget.
|
46 |
-
*/
|
47 |
-
public function register_widget() {
|
48 |
-
register_widget( 'ExactMetrics_Popular_Posts_Widget_Sidebar' );
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Get the rendered HTML for output.
|
53 |
-
*
|
54 |
-
* @param array $atts These are attributes used to build the specific instance, they can be either shortcode
|
55 |
-
* attributes or Gutenberg block props.
|
56 |
-
*
|
57 |
-
* @return string
|
58 |
-
*/
|
59 |
-
public function get_rendered_html( $atts ) {
|
60 |
-
|
61 |
-
$theme = $this->theme;
|
62 |
-
if ( ! empty( $atts['theme'] ) ) {
|
63 |
-
$theme = $atts['theme'];
|
64 |
-
}
|
65 |
-
|
66 |
-
$theme = $this->is_theme_available( $theme );
|
67 |
-
|
68 |
-
if ( ! empty( $atts['post_count'] ) ) {
|
69 |
-
$limit = intval( $atts['post_count'] );
|
70 |
-
} else {
|
71 |
-
$limit = $this->count;
|
72 |
-
}
|
73 |
-
|
74 |
-
$posts = $this->get_posts_to_display();
|
75 |
-
|
76 |
-
if ( empty( $posts ) ) {
|
77 |
-
return '';
|
78 |
-
}
|
79 |
-
|
80 |
-
if ( 'curated' === $this->sort && apply_filters( 'exactmetrics_popular_posts_widget_curated_shuffle', true ) ) {
|
81 |
-
// Randomize the order.
|
82 |
-
shuffle( $posts );
|
83 |
-
}
|
84 |
-
|
85 |
-
$theme_styles = $this->get_theme_props( $theme )->get_theme();
|
86 |
-
|
87 |
-
$label_text = '';
|
88 |
-
if ( isset( $theme_styles['styles']['label'] ) ) {
|
89 |
-
$label_text = isset( $atts['label_text'] ) ? $atts['label_text'] : $theme_styles['styles']['label']['text'];
|
90 |
-
}
|
91 |
-
|
92 |
-
if ( isset( $atts['widget_title'] ) ) {
|
93 |
-
$show_title = (bool) $atts['widget_title'];
|
94 |
-
$title_text = empty( $atts['widget_title_text'] ) ? '' : $atts['widget_title_text'];
|
95 |
-
} else {
|
96 |
-
$show_title = $this->title;
|
97 |
-
$title_text = $this->title_text;
|
98 |
-
}
|
99 |
-
|
100 |
-
$html = '<div class="' . $this->get_wrapper_class( $atts ) . '">';
|
101 |
-
if ( $show_title ) {
|
102 |
-
$html .= '<h2 class="exactmetrics-widget-popular-posts-widget-title">' . wp_kses_post( $title_text ) . '</h2>';
|
103 |
-
}
|
104 |
-
|
105 |
-
$html .= '<ul class="exactmetrics-widget-popular-posts-list">';
|
106 |
-
|
107 |
-
$display_count = 0;
|
108 |
-
foreach ( $posts as $post ) {
|
109 |
-
$display_count ++;
|
110 |
-
if ( $display_count > $limit ) {
|
111 |
-
break;
|
112 |
-
}
|
113 |
-
$this->set_post_shown( $post['id'] );
|
114 |
-
$html .= '<li ' . $this->get_element_style( $theme, 'background', $atts ) . '>';
|
115 |
-
$html .= '<a href="' . $post['link'] . '">';
|
116 |
-
if ( ! empty( $theme_styles['image'] ) && ! empty( $post['image'] ) ) {
|
117 |
-
$html .= '<div class="exactmetrics-widget-popular-posts-image">';
|
118 |
-
$html .= '<img src="' . $post['image'] . '" srcset=" ' . $post['srcset'] . ' " alt="' . esc_attr( $post['title'] ) . '" />';
|
119 |
-
$html .= '</div>';
|
120 |
-
}
|
121 |
-
$html .= '<div class="exactmetrics-widget-popular-posts-text">';
|
122 |
-
if ( isset( $theme_styles['styles']['label'] ) ) {
|
123 |
-
$html .= '<span class="exactmetrics-widget-popular-posts-label" ' . $this->get_element_style( $theme, 'label', $atts ) . '>' . $label_text . '</span>';
|
124 |
-
}
|
125 |
-
$html .= '<span class="exactmetrics-widget-popular-posts-title" ' . $this->get_element_style( $theme, 'title', $atts ) . '>' . $post['title'] . '</span>';
|
126 |
-
$html .= '</div>';// exactmetrics-widget-popular-posts-text.
|
127 |
-
$html .= '</a>';
|
128 |
-
$html .= '</li>';
|
129 |
-
}
|
130 |
-
|
131 |
-
$html .= '</ul></div><p></p>';// Main div.
|
132 |
-
|
133 |
-
return $html;
|
134 |
-
|
135 |
-
}
|
136 |
-
|
137 |
-
/**
|
138 |
-
* Add widget-specific styles based on theme settings.
|
139 |
-
*/
|
140 |
-
public function build_inline_styles() {
|
141 |
-
|
142 |
-
$themes = $this->get_themes_styles_for_output();
|
143 |
-
$styles = '';
|
144 |
-
|
145 |
-
foreach ( $themes as $theme_key => $theme_styles ) {
|
146 |
-
|
147 |
-
if ( ! empty( $theme_styles['background'] ) ) {
|
148 |
-
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-widget-popular-posts-list li {';
|
149 |
-
|
150 |
-
if ( ! empty( $theme_styles['background']['color'] ) ) {
|
151 |
-
$styles .= 'background-color:' . $theme_styles['background']['color'] . ';';
|
152 |
-
}
|
153 |
-
if ( ! empty( $theme_styles['background']['border'] ) ) {
|
154 |
-
$styles .= 'border-color:' . $theme_styles['background']['border'] . ';';
|
155 |
-
}
|
156 |
-
|
157 |
-
$styles .= '}';
|
158 |
-
}
|
159 |
-
|
160 |
-
if ( ! empty( $theme_styles['label'] ) ) {
|
161 |
-
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-widget-popular-posts-label {';
|
162 |
-
|
163 |
-
if ( ! empty( $theme_styles['label']['color'] ) ) {
|
164 |
-
$styles .= 'color:' . $theme_styles['label']['color'] . ';';
|
165 |
-
}
|
166 |
-
|
167 |
-
if ( ! empty( $theme_styles['label']['background'] ) ) {
|
168 |
-
$styles .= 'background-color:' . $theme_styles['label']['background'] . ';';
|
169 |
-
}
|
170 |
-
|
171 |
-
$styles .= '}';
|
172 |
-
}
|
173 |
-
|
174 |
-
if ( ! empty( $theme_styles['title'] ) ) {
|
175 |
-
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-widget-popular-posts-list li .exactmetrics-widget-popular-posts-title {';
|
176 |
-
|
177 |
-
if ( ! empty( $theme_styles['title']['color'] ) ) {
|
178 |
-
$styles .= 'color:' . $theme_styles['title']['color'] . ';';
|
179 |
-
}
|
180 |
-
if ( ! empty( $theme_styles['title']['size'] ) ) {
|
181 |
-
$styles .= 'font-size:' . $theme_styles['title']['size'] . 'px;';
|
182 |
-
}
|
183 |
-
|
184 |
-
$styles .= '}';
|
185 |
-
}
|
186 |
-
|
187 |
-
if ( ! empty( $theme_styles['border'] ) ) {
|
188 |
-
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-border {';
|
189 |
-
|
190 |
-
if ( ! empty( $theme_styles['border']['color'] ) ) {
|
191 |
-
$styles .= 'border-color:' . $theme_styles['border']['color'] . ';';
|
192 |
-
}
|
193 |
-
|
194 |
-
$styles .= '}';
|
195 |
-
}
|
196 |
-
}
|
197 |
-
|
198 |
-
return $styles;
|
199 |
-
}
|
200 |
-
|
201 |
-
/**
|
202 |
-
* Check if we should attempt to automatically insert the inline widget.
|
203 |
-
*/
|
204 |
-
public function maybe_auto_insert() {
|
205 |
-
|
206 |
-
$post_types = $this->post_types;
|
207 |
-
if ( ! empty( $post_types ) && is_singular( $post_types ) && $this->automatic ) {
|
208 |
-
add_filter( 'the_content', array( $this, 'add_inline_posts_to_content' ) );
|
209 |
-
}
|
210 |
-
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* Insert the widget in the content.
|
215 |
-
*
|
216 |
-
* @param string $content The post content.
|
217 |
-
*
|
218 |
-
* @return string
|
219 |
-
*/
|
220 |
-
public function add_inline_posts_to_content( $content ) {
|
221 |
-
|
222 |
-
if ( $this->is_post_excluded() ) {
|
223 |
-
return $content;
|
224 |
-
}
|
225 |
-
|
226 |
-
$content .= $this->shortcode_output( array() );
|
227 |
-
|
228 |
-
return $content;
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Check if the selected theme is available with the current license to avoid showing a theme not available.
|
233 |
-
* Returns the default 'alpha' theme if not available.
|
234 |
-
*
|
235 |
-
* @param string $theme Theme slug for which we are checking.
|
236 |
-
*
|
237 |
-
* @return string
|
238 |
-
*/
|
239 |
-
public function is_theme_available( $theme ) {
|
240 |
-
|
241 |
-
$theme_props = $this->get_theme_props( $theme )->get_theme();
|
242 |
-
|
243 |
-
if ( ! empty( $theme_props['level'] ) && 'lite' === $theme_props['level'] ) {
|
244 |
-
return $theme;
|
245 |
-
}
|
246 |
-
|
247 |
-
return 'alpha';
|
248 |
-
|
249 |
-
}
|
250 |
-
|
251 |
-
}
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Get the current class in a function.
|
255 |
-
*
|
256 |
-
* @return ExactMetrics_Popular_Posts_Widget Instance of the current class.
|
257 |
-
*/
|
258 |
-
function ExactMetrics_Popular_Posts_Widget() {
|
259 |
-
return ExactMetrics_Popular_Posts_Widget::get_instance();
|
260 |
-
}
|
261 |
-
|
262 |
-
ExactMetrics_Popular_Posts_Widget();
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Code specific to the widget Popular Posts widget type.
|
4 |
+
*/
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class ExactMetrics_Popular_Posts_Widget
|
8 |
+
*/
|
9 |
+
class ExactMetrics_Popular_Posts_Widget extends ExactMetrics_Popular_Posts {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* The instance type. Used for loading specific settings.
|
13 |
+
*
|
14 |
+
* @var string
|
15 |
+
*/
|
16 |
+
protected $type = 'widget';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Used to load the setting specific for this class.
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
protected $settings_key = 'popular_posts_widget';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Used for registering the shortcode specific to this class.
|
27 |
+
*
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $shortcode_key = 'exactmetrics_popular_posts_widget';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Widget-specific hooks.
|
34 |
+
*/
|
35 |
+
public function hooks() {
|
36 |
+
parent::hooks();
|
37 |
+
|
38 |
+
add_action( 'wp', array( $this, 'maybe_auto_insert' ) );
|
39 |
+
|
40 |
+
add_action( 'widgets_init', array( $this, 'register_widget' ) );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Register Popular Posts widget.
|
46 |
+
*/
|
47 |
+
public function register_widget() {
|
48 |
+
register_widget( 'ExactMetrics_Popular_Posts_Widget_Sidebar' );
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get the rendered HTML for output.
|
53 |
+
*
|
54 |
+
* @param array $atts These are attributes used to build the specific instance, they can be either shortcode
|
55 |
+
* attributes or Gutenberg block props.
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function get_rendered_html( $atts ) {
|
60 |
+
|
61 |
+
$theme = $this->theme;
|
62 |
+
if ( ! empty( $atts['theme'] ) ) {
|
63 |
+
$theme = $atts['theme'];
|
64 |
+
}
|
65 |
+
|
66 |
+
$theme = $this->is_theme_available( $theme );
|
67 |
+
|
68 |
+
if ( ! empty( $atts['post_count'] ) ) {
|
69 |
+
$limit = intval( $atts['post_count'] );
|
70 |
+
} else {
|
71 |
+
$limit = $this->count;
|
72 |
+
}
|
73 |
+
|
74 |
+
$posts = $this->get_posts_to_display();
|
75 |
+
|
76 |
+
if ( empty( $posts ) ) {
|
77 |
+
return '';
|
78 |
+
}
|
79 |
+
|
80 |
+
if ( 'curated' === $this->sort && apply_filters( 'exactmetrics_popular_posts_widget_curated_shuffle', true ) ) {
|
81 |
+
// Randomize the order.
|
82 |
+
shuffle( $posts );
|
83 |
+
}
|
84 |
+
|
85 |
+
$theme_styles = $this->get_theme_props( $theme )->get_theme();
|
86 |
+
|
87 |
+
$label_text = '';
|
88 |
+
if ( isset( $theme_styles['styles']['label'] ) ) {
|
89 |
+
$label_text = isset( $atts['label_text'] ) ? $atts['label_text'] : $theme_styles['styles']['label']['text'];
|
90 |
+
}
|
91 |
+
|
92 |
+
if ( isset( $atts['widget_title'] ) ) {
|
93 |
+
$show_title = (bool) $atts['widget_title'];
|
94 |
+
$title_text = empty( $atts['widget_title_text'] ) ? '' : $atts['widget_title_text'];
|
95 |
+
} else {
|
96 |
+
$show_title = $this->title;
|
97 |
+
$title_text = $this->title_text;
|
98 |
+
}
|
99 |
+
|
100 |
+
$html = '<div class="' . $this->get_wrapper_class( $atts ) . '">';
|
101 |
+
if ( $show_title ) {
|
102 |
+
$html .= '<h2 class="exactmetrics-widget-popular-posts-widget-title">' . wp_kses_post( $title_text ) . '</h2>';
|
103 |
+
}
|
104 |
+
|
105 |
+
$html .= '<ul class="exactmetrics-widget-popular-posts-list">';
|
106 |
+
|
107 |
+
$display_count = 0;
|
108 |
+
foreach ( $posts as $post ) {
|
109 |
+
$display_count ++;
|
110 |
+
if ( $display_count > $limit ) {
|
111 |
+
break;
|
112 |
+
}
|
113 |
+
$this->set_post_shown( $post['id'] );
|
114 |
+
$html .= '<li ' . $this->get_element_style( $theme, 'background', $atts ) . '>';
|
115 |
+
$html .= '<a href="' . $post['link'] . '">';
|
116 |
+
if ( ! empty( $theme_styles['image'] ) && ! empty( $post['image'] ) ) {
|
117 |
+
$html .= '<div class="exactmetrics-widget-popular-posts-image">';
|
118 |
+
$html .= '<img src="' . $post['image'] . '" srcset=" ' . $post['srcset'] . ' " alt="' . esc_attr( $post['title'] ) . '" />';
|
119 |
+
$html .= '</div>';
|
120 |
+
}
|
121 |
+
$html .= '<div class="exactmetrics-widget-popular-posts-text">';
|
122 |
+
if ( isset( $theme_styles['styles']['label'] ) ) {
|
123 |
+
$html .= '<span class="exactmetrics-widget-popular-posts-label" ' . $this->get_element_style( $theme, 'label', $atts ) . '>' . $label_text . '</span>';
|
124 |
+
}
|
125 |
+
$html .= '<span class="exactmetrics-widget-popular-posts-title" ' . $this->get_element_style( $theme, 'title', $atts ) . '>' . $post['title'] . '</span>';
|
126 |
+
$html .= '</div>';// exactmetrics-widget-popular-posts-text.
|
127 |
+
$html .= '</a>';
|
128 |
+
$html .= '</li>';
|
129 |
+
}
|
130 |
+
|
131 |
+
$html .= '</ul></div><p></p>';// Main div.
|
132 |
+
|
133 |
+
return $html;
|
134 |
+
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Add widget-specific styles based on theme settings.
|
139 |
+
*/
|
140 |
+
public function build_inline_styles() {
|
141 |
+
|
142 |
+
$themes = $this->get_themes_styles_for_output();
|
143 |
+
$styles = '';
|
144 |
+
|
145 |
+
foreach ( $themes as $theme_key => $theme_styles ) {
|
146 |
+
|
147 |
+
if ( ! empty( $theme_styles['background'] ) ) {
|
148 |
+
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-widget-popular-posts-list li {';
|
149 |
+
|
150 |
+
if ( ! empty( $theme_styles['background']['color'] ) ) {
|
151 |
+
$styles .= 'background-color:' . $theme_styles['background']['color'] . ';';
|
152 |
+
}
|
153 |
+
if ( ! empty( $theme_styles['background']['border'] ) ) {
|
154 |
+
$styles .= 'border-color:' . $theme_styles['background']['border'] . ';';
|
155 |
+
}
|
156 |
+
|
157 |
+
$styles .= '}';
|
158 |
+
}
|
159 |
+
|
160 |
+
if ( ! empty( $theme_styles['label'] ) ) {
|
161 |
+
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-widget-popular-posts-label {';
|
162 |
+
|
163 |
+
if ( ! empty( $theme_styles['label']['color'] ) ) {
|
164 |
+
$styles .= 'color:' . $theme_styles['label']['color'] . ';';
|
165 |
+
}
|
166 |
+
|
167 |
+
if ( ! empty( $theme_styles['label']['background'] ) ) {
|
168 |
+
$styles .= 'background-color:' . $theme_styles['label']['background'] . ';';
|
169 |
+
}
|
170 |
+
|
171 |
+
$styles .= '}';
|
172 |
+
}
|
173 |
+
|
174 |
+
if ( ! empty( $theme_styles['title'] ) ) {
|
175 |
+
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-widget-popular-posts-list li .exactmetrics-widget-popular-posts-title {';
|
176 |
+
|
177 |
+
if ( ! empty( $theme_styles['title']['color'] ) ) {
|
178 |
+
$styles .= 'color:' . $theme_styles['title']['color'] . ';';
|
179 |
+
}
|
180 |
+
if ( ! empty( $theme_styles['title']['size'] ) ) {
|
181 |
+
$styles .= 'font-size:' . $theme_styles['title']['size'] . 'px;';
|
182 |
+
}
|
183 |
+
|
184 |
+
$styles .= '}';
|
185 |
+
}
|
186 |
+
|
187 |
+
if ( ! empty( $theme_styles['border'] ) ) {
|
188 |
+
$styles .= '.exactmetrics-popular-posts-styled.exactmetrics-widget-popular-posts-' . $theme_key . ' .exactmetrics-inline-popular-posts-border {';
|
189 |
+
|
190 |
+
if ( ! empty( $theme_styles['border']['color'] ) ) {
|
191 |
+
$styles .= 'border-color:' . $theme_styles['border']['color'] . ';';
|
192 |
+
}
|
193 |
+
|
194 |
+
$styles .= '}';
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
return $styles;
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Check if we should attempt to automatically insert the inline widget.
|
203 |
+
*/
|
204 |
+
public function maybe_auto_insert() {
|
205 |
+
|
206 |
+
$post_types = $this->post_types;
|
207 |
+
if ( ! empty( $post_types ) && is_singular( $post_types ) && $this->automatic ) {
|
208 |
+
add_filter( 'the_content', array( $this, 'add_inline_posts_to_content' ) );
|
209 |
+
}
|
210 |
+
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Insert the widget in the content.
|
215 |
+
*
|
216 |
+
* @param string $content The post content.
|
217 |
+
*
|
218 |
+
* @return string
|
219 |
+
*/
|
220 |
+
public function add_inline_posts_to_content( $content ) {
|
221 |
+
|
222 |
+
if ( $this->is_post_excluded() ) {
|
223 |
+
return $content;
|
224 |
+
}
|
225 |
+
|
226 |
+
$content .= $this->shortcode_output( array() );
|
227 |
+
|
228 |
+
return $content;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Check if the selected theme is available with the current license to avoid showing a theme not available.
|
233 |
+
* Returns the default 'alpha' theme if not available.
|
234 |
+
*
|
235 |
+
* @param string $theme Theme slug for which we are checking.
|
236 |
+
*
|
237 |
+
* @return string
|
238 |
+
*/
|
239 |
+
public function is_theme_available( $theme ) {
|
240 |
+
|
241 |
+
$theme_props = $this->get_theme_props( $theme )->get_theme();
|
242 |
+
|
243 |
+
if ( ! empty( $theme_props['level'] ) && 'lite' === $theme_props['level'] ) {
|
244 |
+
return $theme;
|
245 |
+
}
|
246 |
+
|
247 |
+
return 'alpha';
|
248 |
+
|
249 |
+
}
|
250 |
+
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Get the current class in a function.
|
255 |
+
*
|
256 |
+
* @return ExactMetrics_Popular_Posts_Widget Instance of the current class.
|
257 |
+
*/
|
258 |
+
function ExactMetrics_Popular_Posts_Widget() {
|
259 |
+
return ExactMetrics_Popular_Posts_Widget::get_instance();
|
260 |
+
}
|
261 |
+
|
262 |
+
ExactMetrics_Popular_Posts_Widget();
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.wpbeginner.com/wpbeginner-needs-your-help/
|
|
4 |
Tags: analytics,google analytics,google analytics dashboard,google analytics plugin,google analytics widget,gtag
|
5 |
Requires at least: 4.8.0
|
6 |
Tested up to: 5.8
|
7 |
-
Stable tag: 7.2.
|
8 |
Requires PHP: 5.5
|
9 |
License: GPL v3
|
10 |
|
@@ -170,7 +170,7 @@ You can translate Google Analytics Dashboard for WP by ExactMetrics on [translat
|
|
170 |
4. Want more features? <a href="https://www.exactmetrics.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion">Purchase ExactMetrics Pro</a>!
|
171 |
|
172 |
== Changelog ==
|
173 |
-
= 7.2.
|
174 |
- New In Pro: 7 day traffic Email Summaries
|
175 |
- New In Pro: Compatibility for the Complianz and CookieYes cookie notice plugins.
|
176 |
- Tweak: Cleaned up the outputting of the GA compatibility layer feature.
|
4 |
Tags: analytics,google analytics,google analytics dashboard,google analytics plugin,google analytics widget,gtag
|
5 |
Requires at least: 4.8.0
|
6 |
Tested up to: 5.8
|
7 |
+
Stable tag: 7.2.0
|
8 |
Requires PHP: 5.5
|
9 |
License: GPL v3
|
10 |
|
170 |
4. Want more features? <a href="https://www.exactmetrics.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion">Purchase ExactMetrics Pro</a>!
|
171 |
|
172 |
== Changelog ==
|
173 |
+
= 7.2.0: November 3, 2021 =
|
174 |
- New In Pro: 7 day traffic Email Summaries
|
175 |
- New In Pro: Compatibility for the Complianz and CookieYes cookie notice plugins.
|
176 |
- Tweak: Cleaned up the outputting of the GA compatibility layer feature.
|