Google Analytics Dashboard for WP (GADWP) - Version 7.4.0

Version Description

Download this release

Release Info

Developer manejaam
Plugin Icon 128x128 Google Analytics Dashboard for WP (GADWP)
Version 7.4.0
Comparing to
See all releases

Code changes from version 7.3.4 to 7.4.0

assets/js/frontend-gtag.js CHANGED
@@ -203,7 +203,7 @@ var ExactMetrics = function () {
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 "";
@@ -615,13 +615,6 @@ var ExactMetrics = function () {
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',
@@ -641,7 +634,6 @@ var ExactMetrics = function () {
641
  }
642
 
643
  __gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
644
- setTimeout( __gtagTrackerHitBack, 1000 );
645
  };
646
  } else if ( type == 'cross-hostname' ) {
647
  beforeUnloadChanged = true;
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.lastIndexOf( "." ) + 1 ); /* Remove everything but what's after the first period */
207
  return extension;
208
  } else {
209
  return "";
615
  } else if ( type == 'external' ) {
616
  beforeUnloadChanged = true;
617
  window.onbeforeunload = function ( e ) {
 
 
 
 
 
 
 
618
 
619
  fieldsArray = {
620
  event_category: 'outbound-link',
634
  }
635
 
636
  __gtagTrackerSendDual( 'event', action || link, fieldsArray, valuesArray );
 
637
  };
638
  } else if ( type == 'cross-hostname' ) {
639
  beforeUnloadChanged = true;
assets/js/frontend-gtag.min.js CHANGED
@@ -1,44 +1,43 @@
1
- ;var ExactMetrics=function(){var e=[],i='',r=!1;this.setLastClicked=function(t,n,i){t=typeof t!=='undefined'?t:[];n=typeof n!=='undefined'?n:[];i=typeof i!=='undefined'?i:!1;e.valuesArray=t;e.fieldsArray=n};this.getLastClicked=function(){return e};this.setInternalAsOutboundCategory=function(e){i=e};this.getInternalAsOutboundCategory=function(){return i};this.sendEvent=function(e,t,n){x(e,t,n,[])};function u(){if(window.exactmetrics_debug_mode){return!0}
2
- else{return!1}};function d(e,t,n){var l={};for(var i in e){if(!e.hasOwnProperty(i)){continue};if(t&&t.indexOf(i)===-1){continue};if(n&&n.indexOf(i)>-1){continue};l[i]=e[i]};return l};function b(e,t,n){if(!exactmetrics_frontend.v4_id||e!=='event'){return};var i=n.event_category||'',r=['event_name','event_category','event_label','value',],l=d(n,null,r);l.action=t;var a={'outbound-link':'click','download':'file_download',};__gtagTracker(e,a[i]||i.replace('-','_'),l)};function y(e,t,n){if(!exactmetrics_frontend.ua){return};var l=['event_category','event_label','value',],i=d(n,l);i.send_to=exactmetrics_frontend.ua;__gtagTracker(e,t,i)};function l(t,i,l,a){t=typeof t!=='undefined'?t:'event';i=typeof i!=='undefined'?i:'';a=typeof a!=='undefined'?a:[];l=typeof l!=='undefined'?l:{};y(t,i,l);b(t,i,l);e.valuesArray=a;e.fieldsArray=l;e.fieldsArray.event_action=i;e.tracked=!0;n('Tracked: '+a.type);n(e)};function x(t,i,l,a){t=typeof t!=='undefined'?t:'event';i=typeof i!=='undefined'?i:'';a=typeof a!=='undefined'?a:[];l=typeof l!=='undefined'?l:{};__gtagTracker(t,i,l);e.valuesArray=a;e.fieldsArray=l;e.fieldsArray.event_action=i;e.tracked=!0;n('Tracked: '+a.type);n(e)};function t(t){t=typeof t!=='undefined'?t:[];e.valuesArray=t;e.fieldsArray=[];e.tracked=!1;n('Not Tracked: '+t.exit);n(e)};function n(e){if(u()){console.dir(e)}};function o(e){return e.replace(/^\s+|\s+$/gm,'')};function c(){var n=0,e=document.domain,i=e.split('.'),t='_gd'+(new Date()).getTime();while(n<(i.length-1)&&document.cookie.indexOf(t+'='+t)==-1){e=i.slice(-1-(++n)).join('.');document.cookie=t+'='+t+';domain='+e+';'};document.cookie=t+'=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain='+e+';';return e};function h(e){e=e.toString();e=e.substring(0,(e.indexOf('#')==-1)?e.length:e.indexOf('#'));e=e.substring(0,(e.indexOf('?')==-1)?e.length:e.indexOf('?'));e=e.substring(e.lastIndexOf('/')+1,e.length);if(e.length>0&&e.indexOf('.')!==-1){e=e.substring(e.indexOf('.')+1);return e}
3
  else{return''}};function w(e){return e.which==1||e.which==2||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey};function g(){var e=[];if(typeof exactmetrics_frontend.download_extensions=='string'){e=exactmetrics_frontend.download_extensions.split(',')};return e};function v(){var e=[];if(typeof exactmetrics_frontend.inbound_paths=='string'){e=JSON.parse(exactmetrics_frontend.inbound_paths)};return e};function A(e){if(e.which==1){return'event.which=1'}
4
  else if(e.which==2){return'event.which=2'}
5
  else if(e.metaKey){return'metaKey'}
6
  else if(e.ctrlKey){return'ctrlKey'}
7
  else if(e.shiftKey){return'shiftKey'}
8
  else if(e.altKey){return'altKey'}
9
- else{return''}};function T(e){var f=g(),l=v(),t='unknown',u=e.href,m=h(e.href),d=c(),r=e.hostname,a=e.protocol,k=e.pathname;u=u.toString();var s,p,b=e.getAttribute('data-vars-ga-category');if(b){return b};if(u.match(/^javascript\:/i)){t='internal'}
10
  else if(a&&a.length>0&&(o(a)=='tel'||o(a)=='tel:')){t='tel'}
11
  else if(a&&a.length>0&&(o(a)=='mailto'||o(a)=='mailto:')){t='mailto'}
12
- else if(r&&d&&r.length>0&&d.length>0&&!r.endsWith('.'+d)&&r!==d){t='external'}
13
  else if(k&&JSON.stringify(l)!='{}'&&k.length>0){var y=l.length;for(var n=0;n<y;n++){if(l[n].path&&l[n].label&&l[n].path.length>0&&l[n].label.length>0&&k.startsWith(l[n].path)){t='internal-as-outbound';i='outbound-link-'+l[n].label;break}}}
14
- else if(r&&window.exactmetrics_experimental_mode&&r.length>0&&document.domain.length>0&&r!==document.domain){t='cross-hostname'};if(m&&(t==='unknown'||'external'===t)&&f.length>0&&m.length>0){for(s=0,p=f.length;s<p;++s){if(f[s].length>0&&(u.endsWith(f[s])||f[s]==m)){t='download';break}}};if(t==='unknown'){t='internal'};return t};function O(e,t){var n=(e.target&&!e.target.match(/^_(self|parent|top)$/i))?e.target:!1;if(t.ctrlKey||t.shiftKey||t.metaKey||t.which==2){n='_blank'};return n};function m(e){if(e.getAttribute('data-vars-ga-label')&&e.getAttribute('data-vars-ga-label').replace(/\n/ig,'')){return e.getAttribute('data-vars-ga-label').replace(/\n/ig,'')}
15
  else if(e.title&&e.title.replace(/\n/ig,'')){return e.title.replace(/\n/ig,'')}
16
  else if(e.innerText&&e.innerText.replace(/\n/ig,'')){return e.innerText.replace(/\n/ig,'')}
17
  else if(e.getAttribute('aria-label')&&e.getAttribute('aria-label').replace(/\n/ig,'')){return e.getAttribute('aria-label').replace(/\n/ig,'')}
18
  else if(e.alt&&e.alt.replace(/\n/ig,'')){return e.alt.replace(/\n/ig,'')}
19
  else if(e.textContent&&e.textContent.replace(/\n/ig,'')){return e.textContent.replace(/\n/ig,'')}
20
  else{return undefined}};function K(e){var i=e.children,l=0,a,n;for(var t=0;t<i.length;t++){a=i[t];n=m(a);if(n){return n};if(l==99){return undefined};l++};return undefined};function k(n){var o=n.srcElement||n.target,e=[],k;e.el=o;e.click_type=A(n);if('undefined'===typeof __gtagTracker||!w(n)){e.exit='loaded';t(e);return}
21
- while(o&&(typeof o.tagName=='undefined'||o.tagName.toLowerCase()!='a'||!o.href)){o=o.parentNode};if(o&&o.href&&!o.hasAttribute('xlink:href')){var d=o.href,I=h(o.href),M=g(),S=v(),L=exactmetrics_frontend.home_url,N=c(),a=T(o),x=O(o,n),b=o.getAttribute('data-vars-ga-action'),f=o.getAttribute('data-vars-ga-label');e.el=o;e.el_href=o.href;e.el_protocol=o.protocol;e.el_hostname=o.hostname;e.el_port=o.port;e.el_pathname=o.pathname;e.el_search=o.search;e.el_hash=o.hash;e.el_host=o.host;e.el_classes=o.getAttribute('class');e.el_id=o.id;e.debug_mode=u();e.download_extensions=M;e.inbound_paths=S;e.home_url=L;e.link=d;e.extension=I;e.type=a;e.target=x;e.title=m(o);if(!e.label&&!e.title){e.title=K(o)};if(a!=='internal'&&a!=='javascript'){var y=!1,p=function(){if(y){return};s();y=!0;window.location.href=d},E=function(){e.exit='external';t(e)},D=function(){e.exit='internal-as-outbound';t(e)},C=function(){e.exit='cross-hostname';t(e)};if(x||a=='mailto'||a=='tel'){if(a=='download'){k={event_category:'download',event_label:f||e.title,file_extension:e.extension,file_name:e.link.replace(/^.*\//g,''),link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,}}
22
- else if(a=='tel'){k={event_category:'tel',event_label:f||e.title.replace('tel:',''),tel_number:d.replace('tel:',''),link_text:f||e.title,link_url:d,link_classes:e.el_classes,link_id:e.el_id,}}
23
- else if(a=='mailto'){k={event_category:'mailto',event_label:f||e.title.replace('mailto:',''),email_address:d.replace('mailto:',''),link_text:f||e.title.replace('mailto:',''),link_url:d,link_classes:e.el_classes,link_id:e.el_id,}}
24
- else if(a=='internal-as-outbound'){k={event_category:i,event_label:f||e.title,event_name:'click',is_affiliate_link:!0,affiliate_label:i.replace('outbound-link-',''),link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,}}
25
- else if(a=='external'){k={event_category:'outbound-link',event_label:f||e.title,is_affiliate_link:!1,link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,}}
26
- else if(a=='cross-hostname'){k={event_category:'cross-hostname',event_label:f||e.title,link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,}};if(k){l('event',b||d,k,e)}
27
- else{if(a&&a!='internal'){k={event_category:a,event_label:f||e.title,link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};l('event',b||d,k,e)}
28
  else{e.exit='type';t(e)}}}
29
  else{if(a!='cross-hostname'&&a!='external'&&a!='internal-as-outbound'){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
30
- else{n.returnValue=!1}}};if(a=='download'){k={event_category:'download',event_label:f||e.title,event_callback:p,file_extension:e.extension,file_name:e.link.replace(/^.*\//g,''),link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};l('event',b||d,k,e)}
31
  else if(a=='internal-as-outbound'){r=!0;window.onbeforeunload=function(t){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
32
- else{n.returnValue=!1}};k={event_category:i,event_label:f||e.title,event_callback:p,is_affiliate_link:!0,affiliate_label:i.replace('outbound-link-',''),link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,};if(navigator.sendBeacon){k.transport='beacon'};l('event',b||d,k,e);setTimeout(p,1000)}}
33
- else if(a=='external'){r=!0;window.onbeforeunload=function(t){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
34
- else{n.returnValue=!1}};k={event_category:'outbound-link',event_label:f||e.title,event_callback:p,is_affiliate_link:!1,link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,};if(navigator.sendBeacon){k.transport='beacon'};l('event',b||d,k,e);setTimeout(p,1000)}}
35
  else if(a=='cross-hostname'){r=!0;window.onbeforeunload=function(t){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
36
- else{n.returnValue=!1}};k={event_category:'cross-hostname',event_label:f||e.title,event_callback:p,link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};if(navigator.sendBeacon){k.transport='beacon'};l('event',b||d,k,e);setTimeout(p,1000)}}
37
- else{if(a&&a!=='internal'){k={event_category:a,event_label:f||e.title,event_callback:p,link_text:f||e.title,link_url:d,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};l('event',b||d,k,e)}
38
  else{e.exit='type';t(e)}};if(a!='external'&&a!='cross-hostname'&&a!='internal-as-outbound'){setTimeout(p,1000)}
39
  else{if(a=='external'){setTimeout(E,1100)}
40
  else if(a=='cross-hostname'){setTimeout(C,1100)}
41
- else{setTimeout(D,1100)}};setTimeout(s,100)}}
42
  else{s();e.exit='internal';t(e)}}
43
  else{e.exit='notlink';t(e)}};var f=window.location.hash;function p(){if(exactmetrics_frontend.hash_tracking==='true'&&f!=window.location.hash&&(exactmetrics_frontend.ua||exactmetrics_frontend.v4_id)){f=window.location.hash;if(exactmetrics_frontend.ua){__gtagTracker('config',exactmetrics_frontend.ua,{page_path:location.pathname+location.search+location.hash,})};if(exactmetrics_frontend.v4_id){__gtagTracker('config',exactmetrics_frontend.v4_id,{page_path:location.pathname+location.search+location.hash,})};n('Hash change to: '+location.pathname+location.search+location.hash)}
44
  else{n('Hash change to (untracked): '+location.pathname+location.search+location.hash)}};function s(){if(r){window.onbeforeunload=null}};var a=window;if(a.addEventListener){a.addEventListener('load',function(){document.body.addEventListener('click',k,!1)},!1);window.addEventListener('hashchange',p,!1)}
1
+ ;var ExactMetrics=function(){var e=[],i='',r=!1;this.setLastClicked=function(t,n,i){t=typeof t!=='undefined'?t:[];n=typeof n!=='undefined'?n:[];i=typeof i!=='undefined'?i:!1;e.valuesArray=t;e.fieldsArray=n};this.getLastClicked=function(){return e};this.setInternalAsOutboundCategory=function(e){i=e};this.getInternalAsOutboundCategory=function(){return i};this.sendEvent=function(e,t,n){x(e,t,n,[])};function d(){if(window.exactmetrics_debug_mode){return!0}
2
+ else{return!1}};function c(e,t,n){var l={};for(var i in e){if(!e.hasOwnProperty(i)){continue};if(t&&t.indexOf(i)===-1){continue};if(n&&n.indexOf(i)>-1){continue};l[i]=e[i]};return l};function b(e,t,n){if(!exactmetrics_frontend.v4_id||e!=='event'){return};var i=n.event_category||'',r=['event_name','event_category','event_label','value',],l=c(n,null,r);l.action=t;var a={'outbound-link':'click','download':'file_download',};__gtagTracker(e,a[i]||i.replace('-','_'),l)};function y(e,t,n){if(!exactmetrics_frontend.ua){return};var l=['event_category','event_label','value',],i=c(n,l);i.send_to=exactmetrics_frontend.ua;__gtagTracker(e,t,i)};function l(t,i,l,a){t=typeof t!=='undefined'?t:'event';i=typeof i!=='undefined'?i:'';a=typeof a!=='undefined'?a:[];l=typeof l!=='undefined'?l:{};y(t,i,l);b(t,i,l);e.valuesArray=a;e.fieldsArray=l;e.fieldsArray.event_action=i;e.tracked=!0;n('Tracked: '+a.type);n(e)};function x(t,i,l,a){t=typeof t!=='undefined'?t:'event';i=typeof i!=='undefined'?i:'';a=typeof a!=='undefined'?a:[];l=typeof l!=='undefined'?l:{};__gtagTracker(t,i,l);e.valuesArray=a;e.fieldsArray=l;e.fieldsArray.event_action=i;e.tracked=!0;n('Tracked: '+a.type);n(e)};function t(t){t=typeof t!=='undefined'?t:[];e.valuesArray=t;e.fieldsArray=[];e.tracked=!1;n('Not Tracked: '+t.exit);n(e)};function n(e){if(d()){console.dir(e)}};function o(e){return e.replace(/^\s+|\s+$/gm,'')};function u(){var n=0,e=document.domain,i=e.split('.'),t='_gd'+(new Date()).getTime();while(n<(i.length-1)&&document.cookie.indexOf(t+'='+t)==-1){e=i.slice(-1-(++n)).join('.');document.cookie=t+'='+t+';domain='+e+';'};document.cookie=t+'=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain='+e+';';return e};function h(e){e=e.toString();e=e.substring(0,(e.indexOf('#')==-1)?e.length:e.indexOf('#'));e=e.substring(0,(e.indexOf('?')==-1)?e.length:e.indexOf('?'));e=e.substring(e.lastIndexOf('/')+1,e.length);if(e.length>0&&e.indexOf('.')!==-1){e=e.substring(e.lastIndexOf('.')+1);return e}
3
  else{return''}};function w(e){return e.which==1||e.which==2||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey};function g(){var e=[];if(typeof exactmetrics_frontend.download_extensions=='string'){e=exactmetrics_frontend.download_extensions.split(',')};return e};function v(){var e=[];if(typeof exactmetrics_frontend.inbound_paths=='string'){e=JSON.parse(exactmetrics_frontend.inbound_paths)};return e};function A(e){if(e.which==1){return'event.which=1'}
4
  else if(e.which==2){return'event.which=2'}
5
  else if(e.metaKey){return'metaKey'}
6
  else if(e.ctrlKey){return'ctrlKey'}
7
  else if(e.shiftKey){return'shiftKey'}
8
  else if(e.altKey){return'altKey'}
9
+ else{return''}};function T(e){var f=g(),l=v(),t='unknown',d=e.href,m=h(e.href),c=u(),r=e.hostname,a=e.protocol,k=e.pathname;d=d.toString();var s,p,b=e.getAttribute('data-vars-ga-category');if(b){return b};if(d.match(/^javascript\:/i)){t='internal'}
10
  else if(a&&a.length>0&&(o(a)=='tel'||o(a)=='tel:')){t='tel'}
11
  else if(a&&a.length>0&&(o(a)=='mailto'||o(a)=='mailto:')){t='mailto'}
12
+ else if(r&&c&&r.length>0&&c.length>0&&!r.endsWith('.'+c)&&r!==c){t='external'}
13
  else if(k&&JSON.stringify(l)!='{}'&&k.length>0){var y=l.length;for(var n=0;n<y;n++){if(l[n].path&&l[n].label&&l[n].path.length>0&&l[n].label.length>0&&k.startsWith(l[n].path)){t='internal-as-outbound';i='outbound-link-'+l[n].label;break}}}
14
+ else if(r&&window.exactmetrics_experimental_mode&&r.length>0&&document.domain.length>0&&r!==document.domain){t='cross-hostname'};if(m&&(t==='unknown'||'external'===t)&&f.length>0&&m.length>0){for(s=0,p=f.length;s<p;++s){if(f[s].length>0&&(d.endsWith(f[s])||f[s]==m)){t='download';break}}};if(t==='unknown'){t='internal'};return t};function O(e,t){var n=(e.target&&!e.target.match(/^_(self|parent|top)$/i))?e.target:!1;if(t.ctrlKey||t.shiftKey||t.metaKey||t.which==2){n='_blank'};return n};function m(e){if(e.getAttribute('data-vars-ga-label')&&e.getAttribute('data-vars-ga-label').replace(/\n/ig,'')){return e.getAttribute('data-vars-ga-label').replace(/\n/ig,'')}
15
  else if(e.title&&e.title.replace(/\n/ig,'')){return e.title.replace(/\n/ig,'')}
16
  else if(e.innerText&&e.innerText.replace(/\n/ig,'')){return e.innerText.replace(/\n/ig,'')}
17
  else if(e.getAttribute('aria-label')&&e.getAttribute('aria-label').replace(/\n/ig,'')){return e.getAttribute('aria-label').replace(/\n/ig,'')}
18
  else if(e.alt&&e.alt.replace(/\n/ig,'')){return e.alt.replace(/\n/ig,'')}
19
  else if(e.textContent&&e.textContent.replace(/\n/ig,'')){return e.textContent.replace(/\n/ig,'')}
20
  else{return undefined}};function K(e){var i=e.children,l=0,a,n;for(var t=0;t<i.length;t++){a=i[t];n=m(a);if(n){return n};if(l==99){return undefined};l++};return undefined};function k(n){var o=n.srcElement||n.target,e=[],k;e.el=o;e.click_type=A(n);if('undefined'===typeof __gtagTracker||!w(n)){e.exit='loaded';t(e);return}
21
+ while(o&&(typeof o.tagName=='undefined'||o.tagName.toLowerCase()!='a'||!o.href)){o=o.parentNode};if(o&&o.href&&!o.hasAttribute('xlink:href')){var c=o.href,M=h(o.href),S=g(),D=v(),L=exactmetrics_frontend.home_url,N=u(),a=T(o),x=O(o,n),b=o.getAttribute('data-vars-ga-action'),f=o.getAttribute('data-vars-ga-label');e.el=o;e.el_href=o.href;e.el_protocol=o.protocol;e.el_hostname=o.hostname;e.el_port=o.port;e.el_pathname=o.pathname;e.el_search=o.search;e.el_hash=o.hash;e.el_host=o.host;e.el_classes=o.getAttribute('class');e.el_id=o.id;e.debug_mode=d();e.download_extensions=S;e.inbound_paths=D;e.home_url=L;e.link=c;e.extension=M;e.type=a;e.target=x;e.title=m(o);if(!e.label&&!e.title){e.title=K(o)};if(a!=='internal'&&a!=='javascript'){var y=!1,p=function(){if(y){return};s();y=!0;window.location.href=c},E=function(){e.exit='external';t(e)},I=function(){e.exit='internal-as-outbound';t(e)},C=function(){e.exit='cross-hostname';t(e)};if(x||a=='mailto'||a=='tel'){if(a=='download'){k={event_category:'download',event_label:f||e.title,file_extension:e.extension,file_name:e.link.replace(/^.*\//g,''),link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,}}
22
+ else if(a=='tel'){k={event_category:'tel',event_label:f||e.title.replace('tel:',''),tel_number:c.replace('tel:',''),link_text:f||e.title,link_url:c,link_classes:e.el_classes,link_id:e.el_id,}}
23
+ else if(a=='mailto'){k={event_category:'mailto',event_label:f||e.title.replace('mailto:',''),email_address:c.replace('mailto:',''),link_text:f||e.title.replace('mailto:',''),link_url:c,link_classes:e.el_classes,link_id:e.el_id,}}
24
+ else if(a=='internal-as-outbound'){k={event_category:i,event_label:f||e.title,event_name:'click',is_affiliate_link:!0,affiliate_label:i.replace('outbound-link-',''),link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,}}
25
+ else if(a=='external'){k={event_category:'outbound-link',event_label:f||e.title,is_affiliate_link:!1,link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,}}
26
+ else if(a=='cross-hostname'){k={event_category:'cross-hostname',event_label:f||e.title,link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,}};if(k){l('event',b||c,k,e)}
27
+ else{if(a&&a!='internal'){k={event_category:a,event_label:f||e.title,link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};l('event',b||c,k,e)}
28
  else{e.exit='type';t(e)}}}
29
  else{if(a!='cross-hostname'&&a!='external'&&a!='internal-as-outbound'){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
30
+ else{n.returnValue=!1}}};if(a=='download'){k={event_category:'download',event_label:f||e.title,event_callback:p,file_extension:e.extension,file_name:e.link.replace(/^.*\//g,''),link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};l('event',b||c,k,e)}
31
  else if(a=='internal-as-outbound'){r=!0;window.onbeforeunload=function(t){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
32
+ else{n.returnValue=!1}};k={event_category:i,event_label:f||e.title,event_callback:p,is_affiliate_link:!0,affiliate_label:i.replace('outbound-link-',''),link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,};if(navigator.sendBeacon){k.transport='beacon'};l('event',b||c,k,e);setTimeout(p,1000)}}
33
+ else if(a=='external'){r=!0;window.onbeforeunload=function(t){k={event_category:'outbound-link',event_label:f||e.title,event_callback:p,is_affiliate_link:!1,link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,outbound:!0,};if(navigator.sendBeacon){k.transport='beacon'};l('event',b||c,k,e)}}
 
34
  else if(a=='cross-hostname'){r=!0;window.onbeforeunload=function(t){if(!n.defaultPrevented){if(n.preventDefault){n.preventDefault()}
35
+ else{n.returnValue=!1}};k={event_category:'cross-hostname',event_label:f||e.title,event_callback:p,link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};if(navigator.sendBeacon){k.transport='beacon'};l('event',b||c,k,e);setTimeout(p,1000)}}
36
+ else{if(a&&a!=='internal'){k={event_category:a,event_label:f||e.title,event_callback:p,link_text:f||e.title,link_url:c,link_domain:e.el_hostname,link_classes:e.el_classes,link_id:e.el_id,};l('event',b||c,k,e)}
37
  else{e.exit='type';t(e)}};if(a!='external'&&a!='cross-hostname'&&a!='internal-as-outbound'){setTimeout(p,1000)}
38
  else{if(a=='external'){setTimeout(E,1100)}
39
  else if(a=='cross-hostname'){setTimeout(C,1100)}
40
+ else{setTimeout(I,1100)}};setTimeout(s,100)}}
41
  else{s();e.exit='internal';t(e)}}
42
  else{e.exit='notlink';t(e)}};var f=window.location.hash;function p(){if(exactmetrics_frontend.hash_tracking==='true'&&f!=window.location.hash&&(exactmetrics_frontend.ua||exactmetrics_frontend.v4_id)){f=window.location.hash;if(exactmetrics_frontend.ua){__gtagTracker('config',exactmetrics_frontend.ua,{page_path:location.pathname+location.search+location.hash,})};if(exactmetrics_frontend.v4_id){__gtagTracker('config',exactmetrics_frontend.v4_id,{page_path:location.pathname+location.search+location.hash,})};n('Hash change to: '+location.pathname+location.search+location.hash)}
43
  else{n('Hash change to (untracked): '+location.pathname+location.search+location.hash)}};function s(){if(r){window.onbeforeunload=null}};var a=window;if(a.addEventListener){a.addEventListener('load',function(){document.body.addEventListener('click',k,!1)},!1);window.addEventListener('hashchange',p,!1)}
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.3.4
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.3.4';
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.4.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.4.0';
48
 
49
  /**
50
  * Plugin file.
includes/admin/routes.php CHANGED
@@ -1,1332 +1,1335 @@
1
- <?php
2
- /**
3
- * Routes for VUE are registered here.
4
- *
5
- * @package exactmetrics
6
- */
7
-
8
- /**
9
- * Class ExactMetrics_Rest_Routes
10
- */
11
- class ExactMetrics_Rest_Routes {
12
-
13
- /**
14
- * ExactMetrics_Rest_Routes constructor.
15
- */
16
- public function __construct() {
17
-
18
- add_action( 'wp_ajax_exactmetrics_vue_get_license', array( $this, 'get_license' ) );
19
- add_action( 'wp_ajax_exactmetrics_vue_get_profile', array( $this, 'get_profile' ) );
20
- add_action( 'wp_ajax_exactmetrics_vue_get_settings', array( $this, 'get_settings' ) );
21
- add_action( 'wp_ajax_exactmetrics_vue_update_settings', array( $this, 'update_settings' ) );
22
- add_action( 'wp_ajax_exactmetrics_vue_update_settings_bulk', array( $this, 'update_settings_bulk' ) );
23
- add_action( 'wp_ajax_exactmetrics_vue_get_addons', array( $this, 'get_addons' ) );
24
- add_action( 'wp_ajax_exactmetrics_update_manual_ua', array( $this, 'update_manual_ua' ) );
25
- add_action( 'wp_ajax_exactmetrics_update_manual_v4', array( $this, 'update_manual_v4' ) );
26
- add_action( 'wp_ajax_exactmetrics_update_dual_tracking_id', array( $this, 'update_dual_tracking_id' ) );
27
- add_action( 'wp_ajax_exactmetrics_update_measurement_protocol_secret', array( $this, 'update_measurement_protocol_secret' ) );
28
- add_action( 'wp_ajax_exactmetrics_vue_get_report_data', array( $this, 'get_report_data' ) );
29
- add_action( 'wp_ajax_exactmetrics_vue_install_plugin', array( $this, 'install_plugin' ) );
30
- add_action( 'wp_ajax_exactmetrics_vue_notice_status', array( $this, 'get_notice_status' ) );
31
- add_action( 'wp_ajax_exactmetrics_vue_notice_dismiss', array( $this, 'dismiss_notice' ) );
32
- add_action( 'wp_ajax_exactmetrics_vue_grab_popular_posts_report', array(
33
- $this,
34
- 'check_popular_posts_report'
35
- ) );
36
- add_action( 'wp_ajax_exactmetrics_vue_popular_posts_update_theme_setting', array(
37
- $this,
38
- 'update_popular_posts_theme_setting'
39
- ) );
40
-
41
- // TODO: remove function from Google Optimize Addon.
42
- add_action( 'wp_ajax_exactmetrics_get_posts', array( $this, 'get_posts' ) );
43
-
44
- // Search for taxonomies.
45
- add_action( 'wp_ajax_exactmetrics_get_terms', array( $this, 'get_taxonomy_terms' ) );
46
-
47
- add_action( 'wp_ajax_exactmetrics_get_post_types', array( $this, 'get_post_types' ) );
48
-
49
- add_action( 'wp_ajax_exactmetrics_handle_settings_import', array( $this, 'handle_settings_import' ) );
50
-
51
- add_action( 'admin_notices', array( $this, 'hide_old_notices' ), 0 );
52
-
53
- add_action( 'wp_ajax_exactmetrics_vue_dismiss_first_time_notice', array(
54
- $this,
55
- 'dismiss_first_time_notice'
56
- ) );
57
- }
58
-
59
- /**
60
- * Ajax handler for grabbing the license
61
- */
62
- public function get_license() {
63
-
64
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
65
-
66
- if ( ! current_user_can( 'exactmetrics_view_dashboard' ) || ! exactmetrics_is_pro_version() ) {
67
- return;
68
- }
69
-
70
- $site_license = array(
71
- 'key' => ExactMetrics()->license->get_site_license_key(),
72
- 'type' => ExactMetrics()->license->get_site_license_type(),
73
- 'is_disabled' => ExactMetrics()->license->site_license_disabled(),
74
- 'is_expired' => ExactMetrics()->license->site_license_expired(),
75
- 'is_invalid' => ExactMetrics()->license->site_license_invalid(),
76
- );
77
- $network_license = array(
78
- 'key' => ExactMetrics()->license->get_network_license_key(),
79
- 'type' => ExactMetrics()->license->get_network_license_type(),
80
- 'is_disabled' => ExactMetrics()->license->network_license_disabled(),
81
- 'is_expired' => ExactMetrics()->license->network_license_expired(),
82
- 'is_invalid' => ExactMetrics()->license->network_license_disabled(),
83
- );
84
-
85
- wp_send_json( array(
86
- 'site' => $site_license,
87
- 'network' => $network_license,
88
- ) );
89
-
90
- }
91
-
92
- /**
93
- * Ajax handler for grabbing the current authenticated profile.
94
- */
95
- public function get_profile() {
96
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
97
-
98
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
99
- return;
100
- }
101
-
102
- $auth = ExactMetrics()->auth;
103
-
104
- wp_send_json( array(
105
- 'ua' => $auth->get_ua(),
106
- 'v4' => $auth->get_v4_id(),
107
- 'viewname' => $auth->get_viewname(),
108
- 'manual_ua' => $auth->get_manual_ua(),
109
- 'manual_v4' => $auth->get_manual_v4_id(),
110
- 'measurement_protocol_secret' => $auth->get_measurement_protocol_secret(),
111
- 'network_ua' => $auth->get_network_ua(),
112
- 'network_v4' => $auth->get_network_v4_id(),
113
- 'network_viewname' => $auth->get_network_viewname(),
114
- 'network_manual_ua' => $auth->get_network_manual_ua(),
115
- 'network_measurement_protocol_secret' => $auth->get_network_measurement_protocol_secret(),
116
- 'connected_type' => $auth->get_connected_type(),
117
- ) );
118
-
119
- }
120
-
121
- /**
122
- * Ajax handler for grabbing the settings.
123
- */
124
- public function get_settings() {
125
-
126
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
127
-
128
- if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
129
- return;
130
- }
131
-
132
- $options = exactmetrics_get_options();
133
-
134
- // Array fields are needed even if empty.
135
- $array_fields = array( 'view_reports', 'save_settings', 'ignore_users' );
136
- foreach ( $array_fields as $array_field ) {
137
- if ( ! isset( $options[ $array_field ] ) ) {
138
- $options[ $array_field ] = array();
139
- }
140
- }
141
-
142
- //add email summaries options
143
- if ( exactmetrics_is_pro_version() ) {
144
- $default_email = array(
145
- 'email' => get_option( 'admin_email' ),
146
- );
147
-
148
- if ( ! isset( $options['email_summaries'] ) ) {
149
- $options['email_summaries'] = 'on';
150
- }
151
-
152
- if ( ! isset( $options['summaries_email_addresses'] ) ) {
153
- $options['summaries_email_addresses'] = array(
154
- $default_email,
155
- );
156
- }
157
-
158
- if ( ! isset( $options['summaries_html_template'] ) ) {
159
- $options['summaries_html_template'] = 'yes';
160
- }
161
-
162
-
163
- if ( ! isset( $options['summaries_carbon_copy'] ) ) {
164
- $options['summaries_carbon_copy'] = 'no';
165
- }
166
-
167
-
168
- if ( ! isset( $options['summaries_header_image'] ) ) {
169
- $options['summaries_header_image'] = '';
170
- }
171
-
172
- if ( ! isset( $options['local_gtag_file_modified_at'] ) ) {
173
- $options['local_gtag_file_modified_at'] = '';
174
- }
175
- }
176
-
177
- wp_send_json( $options );
178
-
179
- }
180
-
181
- /**
182
- * Ajax handler for updating the settings.
183
- */
184
- public function update_settings() {
185
-
186
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
187
-
188
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
189
- return;
190
- }
191
-
192
- if ( isset( $_POST['setting'] ) ) {
193
- $setting = sanitize_text_field( wp_unslash( $_POST['setting'] ) );
194
- if ( isset( $_POST['value'] ) ) {
195
- $value = $this->handle_sanitization( $setting, $_POST['value'] );
196
- exactmetrics_update_option( $setting, $value );
197
- do_action( 'exactmetrics_after_update_settings', $setting, $value );
198
- } else {
199
- exactmetrics_update_option( $setting, false );
200
- do_action( 'exactmetrics_after_update_settings', $setting, false );
201
- }
202
- }
203
-
204
- wp_send_json_success();
205
-
206
- }
207
-
208
- /**
209
- * Ajax handler for updating the settings.
210
- */
211
- public function update_settings_bulk() {
212
-
213
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
214
-
215
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
216
- return;
217
- }
218
-
219
- if ( isset( $_POST['settings'] ) ) {
220
- $settings = json_decode( sanitize_text_field( wp_unslash( $_POST['settings'] ) ), true );
221
- foreach ( $settings as $setting => $value ) {
222
- $value = $this->handle_sanitization( $setting, $value );
223
- exactmetrics_update_option( $setting, $value );
224
- do_action( 'exactmetrics_after_update_settings', $setting, $value );
225
- }
226
- }
227
-
228
- wp_send_json_success();
229
-
230
- }
231
-
232
- /**
233
- * Sanitization specific to each field.
234
- *
235
- * @param string $field The key of the field to sanitize.
236
- * @param string $value The value of the field to sanitize.
237
- *
238
- * @return mixed The sanitized input.
239
- */
240
- private function handle_sanitization( $field, $value ) {
241
-
242
- $value = wp_unslash( $value );
243
-
244
- // Textarea fields.
245
- $textarea_fields = array();
246
-
247
- if ( in_array( $field, $textarea_fields, true ) ) {
248
- if ( function_exists( 'sanitize_textarea_field' ) ) {
249
- return sanitize_textarea_field( $value );
250
- } else {
251
- return wp_kses( $value, array() );
252
- }
253
- }
254
-
255
- $array_value = json_decode( $value, true );
256
- if ( is_array( $array_value ) ) {
257
- $value = $array_value;
258
- // Don't save empty values.
259
- foreach ( $value as $key => $item ) {
260
- if ( is_array( $item ) ) {
261
- $empty = true;
262
- foreach ( $item as $item_value ) {
263
- if ( ! empty( $item_value ) ) {
264
- $empty = false;
265
- }
266
- }
267
- if ( $empty ) {
268
- unset( $value[ $key ] );
269
- }
270
- }
271
- }
272
-
273
- // Reset array keys because JavaScript can't handle arrays with non-sequential keys.
274
- $value = array_values( $value );
275
-
276
- return $value;
277
- }
278
-
279
- return sanitize_text_field( $value );
280
-
281
- }
282
-
283
- /**
284
- * Return the state of the addons ( installed, activated )
285
- */
286
- public function get_addons() {
287
-
288
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
289
-
290
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
291
- return;
292
- }
293
-
294
- if ( isset( $_POST['network'] ) && intval( $_POST['network'] ) > 0 ) {
295
- define( 'WP_NETWORK_ADMIN', true );
296
- }
297
-
298
- $addons_data = exactmetrics_get_addons();
299
- $parsed_addons = array();
300
- $installed_plugins = get_plugins();
301
-
302
- if ( ! is_array( $addons_data ) ) {
303
- $addons_data = array();
304
- }
305
-
306
- foreach ( $addons_data as $addons_type => $addons ) {
307
- foreach ( $addons as $addon ) {
308
- $slug = 'exactmetrics-' . $addon->slug;
309
- if ( 'exactmetrics-ecommerce' === $slug && 'm' === $slug[0] ) {
310
- $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
311
- if ( empty( $addon->installed ) ) {
312
- $slug = 'ga-ecommerce';
313
- $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
314
- }
315
- } else {
316
- $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
317
- }
318
- $parsed_addons[ $addon->slug ] = $addon;
319
- }
320
- }
321
-
322
- // Include data about the plugins needed by some addons ( WooCommerce, EDD, Google AMP, CookieBot, etc ).
323
- // WooCommerce.
324
- $parsed_addons['woocommerce'] = array(
325
- 'active' => class_exists( 'WooCommerce' ),
326
- );
327
- // Edd.
328
- $parsed_addons['easy_digital_downloads'] = array(
329
- 'active' => class_exists( 'Easy_Digital_Downloads' ),
330
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-edd.png',
331
- 'title' => 'Easy Digital Downloads',
332
- 'excerpt' => __( 'Easy digital downloads plugin.', 'google-analytics-dashboard-for-wp' ),
333
- 'installed' => array_key_exists( 'easy-digital-downloads/easy-digital-downloads.php', $installed_plugins ),
334
- 'basename' => 'easy-digital-downloads/easy-digital-downloads.php',
335
- 'slug' => 'easy-digital-downloads',
336
- 'settings' => admin_url( 'edit.php?post_type=download' ),
337
- );
338
- // MemberPress.
339
- $parsed_addons['memberpress'] = array(
340
- 'active' => defined( 'MEPR_VERSION' ) && version_compare( MEPR_VERSION, '1.3.43', '>' ),
341
- );
342
- // LifterLMS.
343
- $parsed_addons['lifterlms'] = array(
344
- 'active' => function_exists( 'LLMS' ) && version_compare( LLMS()->version, '3.32.0', '>=' ),
345
- );
346
- // Restrict Content Pro.
347
- $parsed_addons['rcp'] = array(
348
- 'active' => class_exists( 'Restrict_Content_Pro' ) && version_compare( RCP_PLUGIN_VERSION, '3.5.4', '>=' ),
349
- );
350
- // GiveWP.
351
- $parsed_addons['givewp'] = array(
352
- 'active' => function_exists( 'Give' ),
353
- );
354
- // GiveWP Analytics.
355
- $parsed_addons['givewp_google_analytics'] = array(
356
- 'active' => function_exists( 'Give_Google_Analytics' ),
357
- );
358
- // Cookiebot.
359
- $parsed_addons['cookiebot'] = array(
360
- 'active' => function_exists( 'cookiebot_active' ) && cookiebot_active(),
361
- );
362
- // Cookie Notice.
363
- $parsed_addons['cookie_notice'] = array(
364
- 'active' => class_exists( 'Cookie_Notice' ),
365
- );
366
- // Complianz.
367
- $parsed_addons['complianz'] = array(
368
- 'active' => defined( 'cmplz_plugin') || defined( 'cmplz_premium'),
369
- );
370
- // Cookie Yes
371
- $parsed_addons['cookie_yes'] = array(
372
- 'active' => defined( 'CLI_SETTINGS_FIELD'),
373
- );
374
- // Fb Instant Articles.
375
- $parsed_addons['instant_articles'] = array(
376
- 'active' => defined( 'IA_PLUGIN_VERSION' ) && version_compare( IA_PLUGIN_VERSION, '3.3.4', '>' ),
377
- );
378
- // Google AMP.
379
- $parsed_addons['google_amp'] = array(
380
- 'active' => defined( 'AMP__FILE__' ),
381
- );
382
- // Yoast SEO.
383
- $parsed_addons['yoast_seo'] = array(
384
- 'active' => defined( 'WPSEO_VERSION' ),
385
- );
386
- // EasyAffiliate.
387
- $parsed_addons['easy_affiliate'] = array(
388
- 'active' => defined( 'ESAF_EDITION' ),
389
- );
390
- $parsed_addons['affiliate_wp'] = array(
391
- 'active' => function_exists( 'affiliate_wp' ) && defined( 'AFFILIATEWP_VERSION' ),
392
- );
393
- // WPForms.
394
- $parsed_addons['wpforms-lite'] = array(
395
- 'active' => function_exists( 'wpforms' ),
396
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-wpforms.png',
397
- 'title' => 'WPForms',
398
- 'excerpt' => __( 'The best drag & drop WordPress form builder. Easily create beautiful contact forms, surveys, payment forms, and more with our 150+ form templates. Trusted by over 4 million websites as the best forms plugin', 'google-analytics-dashboard-for-wp' ),
399
- 'installed' => array_key_exists( 'wpforms-lite/wpforms.php', $installed_plugins ),
400
- 'basename' => 'wpforms-lite/wpforms.php',
401
- 'slug' => 'wpforms-lite',
402
- 'settings' => admin_url( 'admin.php?page=wpforms-overview' ),
403
- );
404
- // AIOSEO.
405
- $parsed_addons['aioseo'] = array(
406
- 'active' => function_exists( 'aioseo' ),
407
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-all-in-one-seo.png',
408
- 'title' => 'AIOSEO',
409
- 'excerpt' => __( 'The original WordPress SEO plugin and toolkit that improves your website’s search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.', 'google-analytics-dashboard-for-wp' ),
410
- 'installed' => array_key_exists( 'all-in-one-seo-pack/all_in_one_seo_pack.php', $installed_plugins ),
411
- 'basename' => ( exactmetrics_is_installed_aioseo_pro() ) ? 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php' : 'all-in-one-seo-pack/all_in_one_seo_pack.php',
412
- 'slug' => 'all-in-one-seo-pack',
413
- 'settings' => admin_url( 'admin.php?page=aioseo' ),
414
- );
415
- // OptinMonster.
416
- $parsed_addons['optinmonster'] = array(
417
- 'active' => class_exists( 'OMAPI' ),
418
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-om.png',
419
- 'title' => 'OptinMonster',
420
- 'excerpt' => __( 'Instantly get more subscribers, leads, and sales with the #1 conversion optimization toolkit. Create high converting popups, announcement bars, spin a wheel, and more with smart targeting and personalization.', 'google-analytics-dashboard-for-wp' ),
421
- 'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
422
- 'basename' => 'optinmonster/optin-monster-wp-api.php',
423
- 'slug' => 'optinmonster',
424
- 'settings' => admin_url( 'admin.php?page=optin-monster-dashboard' ),
425
- );
426
- // WP Mail Smtp.
427
- $parsed_addons['wp-mail-smtp'] = array(
428
- 'active' => function_exists( 'wp_mail_smtp' ),
429
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-smtp.png',
430
- 'title' => 'WP Mail SMTP',
431
- 'excerpt' => __( 'Improve your WordPress email deliverability and make sure that your website emails reach user’s inbox with the #1 SMTP plugin for WordPress. Over 2 million websites use it to fix WordPress email issues.', 'google-analytics-dashboard-for-wp' ),
432
- 'installed' => array_key_exists( 'wp-mail-smtp/wp_mail_smtp.php', $installed_plugins ),
433
- 'basename' => 'wp-mail-smtp/wp_mail_smtp.php',
434
- 'slug' => 'wp-mail-smtp',
435
- );
436
- // SeedProd.
437
- $parsed_addons['coming-soon'] = array(
438
- 'active' => defined( 'SEEDPROD_VERSION' ),
439
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-seedprod.png',
440
- 'title' => 'SeedProd',
441
- 'excerpt' => __( 'The fastest drag & drop landing page builder for WordPress. Create custom landing pages without writing code, connect them with your CRM, collect subscribers, and grow your audience. Trusted by 1 million sites.', 'google-analytics-dashboard-for-wp' ),
442
- 'installed' => array_key_exists( 'coming-soon/coming-soon.php', $installed_plugins ),
443
- 'basename' => 'coming-soon/coming-soon.php',
444
- 'slug' => 'coming-soon',
445
- 'settings' => admin_url( 'admin.php?page=seedprod_lite' ),
446
- );
447
- // RafflePress
448
- $parsed_addons['rafflepress'] = array(
449
- 'active' => function_exists( 'rafflepress_lite_activation' ),
450
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/pluign-rafflepress.png',
451
- 'title' => 'RafflePress',
452
- 'excerpt' => __( 'Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.', 'google-analytics-dashboard-for-wp' ),
453
- 'installed' => array_key_exists( 'rafflepress/rafflepress.php', $installed_plugins ),
454
- 'basename' => 'rafflepress/rafflepress.php',
455
- 'slug' => 'rafflepress',
456
- 'settings' => admin_url( 'admin.php?page=rafflepress_lite' ),
457
- );
458
- // TrustPulse
459
- $parsed_addons['trustpulse-api'] = array(
460
- 'active' => class_exists( 'TPAPI' ),
461
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-trust-pulse.png',
462
- 'title' => 'TrustPulse',
463
- 'excerpt' => __( 'Boost your sales and conversions by up to 15% with real-time social proof notifications. TrustPulse helps you show live user activity and purchases to help convince other users to purchase.', 'google-analytics-dashboard-for-wp' ),
464
- 'installed' => array_key_exists( 'trustpulse-api/trustpulse.php', $installed_plugins ),
465
- 'basename' => 'trustpulse-api/trustpulse.php',
466
- 'slug' => 'trustpulse-api',
467
- );
468
- // Smash Balloon (Instagram)
469
- $parsed_addons['smash-balloon-instagram'] = array(
470
- 'active' => defined( 'SBIVER' ),
471
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-smash-balloon.png',
472
- 'title' => 'Smash Balloon Instagram Feeds',
473
- 'excerpt' => __( 'Easily display Instagram content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'google-analytics-dashboard-for-wp' ),
474
- 'installed' => array_key_exists( 'instagram-feed/instagram-feed.php', $installed_plugins ),
475
- 'basename' => 'instagram-feed/instagram-feed.php',
476
- 'slug' => 'instagram-feed',
477
- 'settings' => admin_url( 'admin.php?page=sb-instagram-feed' ),
478
- );
479
- // Smash Balloon (Facebook)
480
- $parsed_addons['smash-balloon-facebook'] = array(
481
- 'active' => defined( 'CFFVER' ),
482
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-smash-balloon.png',
483
- 'title' => 'Smash Balloon Facebook Feeds',
484
- 'excerpt' => __( 'Easily display Facebook content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'google-analytics-dashboard-for-wp' ),
485
- 'installed' => array_key_exists( 'custom-facebook-feed/custom-facebook-feed.php', $installed_plugins ),
486
- 'basename' => 'custom-facebook-feed/custom-facebook-feed.php',
487
- 'slug' => 'custom-facebook-feed',
488
- 'settings' => admin_url( 'admin.php?page=cff-feed-builder' ),
489
- );
490
- // PushEngage
491
- $parsed_addons['pushengage'] = array(
492
- 'active' => method_exists( 'Pushengage', 'init' ),
493
- 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-pushengage.svg',
494
- 'title' => 'PushEngage',
495
- 'excerpt' => __( 'Connect with your visitors after they leave your website with the leading web push notification software. Over 10,000+ businesses worldwide use PushEngage to send 9 billion notifications each month.', 'google-analytics-dashboard-for-wp' ),
496
- 'installed' => array_key_exists( 'pushengage/main.php', $installed_plugins ),
497
- 'basename' => 'pushengage/main.php',
498
- 'slug' => 'pushengage',
499
- );
500
- // Pretty Links
501
- $parsed_addons['pretty-link'] = array(
502
- 'active' => class_exists( 'PrliBaseController' ),
503
- 'icon' => '',
504
- 'title' => 'Pretty Links',
505
- 'excerpt' => __( 'Pretty Links helps you shrink, beautify, track, manage and share any URL on or off of your WordPress website. Create links that look how you want using your own domain name!', 'google-analytics-dashboard-for-wp' ),
506
- 'installed' => array_key_exists( 'pretty-link/pretty-link.php', $installed_plugins ),
507
- 'basename' => 'pretty-link/pretty-link.php',
508
- 'slug' => 'pretty-link',
509
- 'settings' => admin_url( 'edit.php?post_type=pretty-link' ),
510
- );
511
- // Thirsty Affiliates
512
- $parsed_addons['thirstyaffiliates'] = array(
513
- 'active' => class_exists( 'ThirstyAffiliates' ),
514
- 'icon' => '',
515
- 'title' => 'Thirsty Affiliates',
516
- 'excerpt' => __( 'ThirstyAffiliates is a revolution in affiliate link management. Collect, collate and store your affiliate links for use in your posts and pages.', 'google-analytics-dashboard-for-wp' ),
517
- 'installed' => array_key_exists( 'thirstyaffiliates/thirstyaffiliates.php', $installed_plugins ),
518
- 'basename' => 'thirstyaffiliates/thirstyaffiliates.php',
519
- 'slug' => 'thirstyaffiliates',
520
- 'settings' => admin_url( 'edit.php?post_type=thirstylink' ),
521
- );
522
- if ( function_exists( 'WC' ) ) {
523
- // Advanced Coupons
524
- $parsed_addons['advancedcoupons'] = array(
525
- 'active' => class_exists( 'ACFWF' ),
526
- 'icon' => '',
527
- 'title' => 'Advanced Coupons',
528
- 'excerpt' => __( 'Advanced Coupons for WooCommerce (Free Version) gives WooCommerce store owners extra coupon features so they can market their stores better.', 'google-analytics-dashboard-for-wp' ),
529
- 'installed' => array_key_exists( 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php', $installed_plugins ),
530
- 'basename' => 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php',
531
- 'slug' => 'advanced-coupons-for-woocommerce-free',
532
- 'settings' => admin_url( 'edit.php?post_type=shop_coupon&acfw' ),
533
- );
534
- }
535
- // Gravity Forms.
536
- $parsed_addons['gravity_forms'] = array(
537
- 'active' => class_exists( 'GFCommon' ),
538
- );
539
- // Formidable Forms.
540
- $parsed_addons['formidable_forms'] = array(
541
- 'active' => class_exists( 'FrmHooksController' ),
542
- );
543
- // Manual UA Addon.
544
- if ( ! isset( $parsed_addons['manual_ua'] ) ) {
545
- $parsed_addons['manual_ua'] = array(
546
- 'active' => class_exists( 'ExactMetrics_Manual_UA' ),
547
- );
548
- }
549
-
550
- wp_send_json( $parsed_addons );
551
- }
552
-
553
- public function get_addon( $installed_plugins, $addons_type, $addon, $slug ) {
554
- $active = false;
555
- $installed = false;
556
- $plugin_basename = exactmetrics_get_plugin_basename_from_slug( $slug );
557
-
558
- if ( isset( $installed_plugins[ $plugin_basename ] ) ) {
559
- $installed = true;
560
-
561
- if ( is_multisite() && is_network_admin() ) {
562
- $active = is_plugin_active_for_network( $plugin_basename );
563
- } else {
564
- $active = is_plugin_active( $plugin_basename );
565
- }
566
- }
567
- if ( empty( $addon->url ) ) {
568
- $addon->url = '';
569
- }
570
-
571
- $active_version = false;
572
- if ( $active ) {
573
- if ( ! empty( $installed_plugins[ $plugin_basename ]['Version'] ) ) {
574
- $active_version = $installed_plugins[ $plugin_basename ]['Version'];
575
- }
576
- }
577
-
578
- $addon->type = $addons_type;
579
- $addon->installed = $installed;
580
- $addon->active_version = $active_version;
581
- $addon->active = $active;
582
- $addon->basename = $plugin_basename;
583
-
584
- return $addon;
585
- }
586
-
587
- /**
588
- * Use custom notices in the Vue app on the Settings screen.
589
- */
590
- public function hide_old_notices() {
591
-
592
- global $wp_version;
593
- if ( version_compare( $wp_version, '4.6', '<' ) ) {
594
- // remove_all_actions triggers an infinite loop on older versions.
595
- return;
596
- }
597
-
598
- $screen = get_current_screen();
599
- // Bail if we're not on a ExactMetrics screen.
600
- if ( empty( $screen->id ) || strpos( $screen->id, 'exactmetrics' ) === false ) {
601
- return;
602
- }
603
-
604
- // Hide admin notices on the settings screen.
605
- if ( exactmetrics_is_settings_page() ) {
606
- remove_all_actions( 'admin_notices' );
607
- }
608
-
609
- }
610
-
611
- /**
612
- * Update manual ua.
613
- */
614
- public function update_manual_ua() {
615
-
616
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
617
-
618
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
619
- return;
620
- }
621
-
622
- $manual_ua_code = isset( $_POST['manual_ua_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_ua_code'] ) ) : '';
623
- $manual_ua_code = exactmetrics_is_valid_ua( $manual_ua_code ); // Also sanitizes the string.
624
- if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
625
- define( 'WP_NETWORK_ADMIN', true );
626
- }
627
- $manual_ua_code_old = is_network_admin() ? ExactMetrics()->auth->get_network_manual_ua() : ExactMetrics()->auth->get_manual_ua();
628
-
629
- if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old === $manual_ua_code ) {
630
- // Same code we had before
631
- // Do nothing.
632
- wp_send_json_success();
633
- } else if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old !== $manual_ua_code ) {
634
- // Different UA code.
635
- if ( is_network_admin() ) {
636
- ExactMetrics()->auth->set_network_manual_ua( $manual_ua_code );
637
- } else {
638
- ExactMetrics()->auth->set_manual_ua( $manual_ua_code );
639
- }
640
- } else if ( $manual_ua_code && empty( $manual_ua_code_old ) ) {
641
- // Move to manual.
642
- if ( is_network_admin() ) {
643
- ExactMetrics()->auth->set_network_manual_ua( $manual_ua_code );
644
- } else {
645
- ExactMetrics()->auth->set_manual_ua( $manual_ua_code );
646
- }
647
- } else if ( empty( $manual_ua_code ) && $manual_ua_code_old ) {
648
- // Deleted manual.
649
- if ( is_network_admin() ) {
650
- ExactMetrics()->auth->delete_network_manual_ua();
651
- } else {
652
- ExactMetrics()->auth->delete_manual_ua();
653
- }
654
- } else if ( isset( $_POST['manual_ua_code'] ) && empty( $manual_ua_code ) ) {
655
- wp_send_json_error( array(
656
- 'error' => __( 'Invalid UA code', 'google-analytics-dashboard-for-wp' ),
657
- ) );
658
- }
659
-
660
- wp_send_json_success();
661
- }
662
-
663
- /**
664
- * Update manual v4.
665
- */
666
- public function update_manual_v4() {
667
-
668
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
669
-
670
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
671
- return;
672
- }
673
-
674
- $manual_v4_code = isset( $_POST['manual_v4_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_v4_code'] ) ) : '';
675
- $manual_v4_code = exactmetrics_is_valid_v4_id( $manual_v4_code ); // Also sanitizes the string.
676
-
677
- if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
678
- define( 'WP_NETWORK_ADMIN', true );
679
- }
680
- $manual_v4_code_old = is_network_admin() ? ExactMetrics()->auth->get_network_manual_v4_id() : ExactMetrics()->auth->get_manual_v4_id();
681
-
682
- if ( $manual_v4_code && $manual_v4_code_old && $manual_v4_code_old === $manual_v4_code ) {
683
- // Same code we had before
684
- // Do nothing.
685
- wp_send_json_success();
686
- } else if ( $manual_v4_code && $manual_v4_code_old && $manual_v4_code_old !== $manual_v4_code ) {
687
- // Different UA code.
688
- if ( is_network_admin() ) {
689
- ExactMetrics()->auth->set_network_manual_v4_id( $manual_v4_code );
690
- } else {
691
- ExactMetrics()->auth->set_manual_v4_id( $manual_v4_code );
692
- }
693
- } else if ( $manual_v4_code && empty( $manual_v4_code_old ) ) {
694
- // Move to manual.
695
- if ( is_network_admin() ) {
696
- ExactMetrics()->auth->set_network_manual_v4_id( $manual_v4_code );
697
- } else {
698
- ExactMetrics()->auth->set_manual_v4_id( $manual_v4_code );
699
- }
700
- } else if ( empty( $manual_v4_code ) && $manual_v4_code_old ) {
701
- // Deleted manual.
702
- if ( is_network_admin() ) {
703
- ExactMetrics()->auth->delete_network_manual_v4_id();
704
- } else {
705
- ExactMetrics()->auth->delete_manual_v4_id();
706
- }
707
- } else if ( isset( $_POST['manual_v4_code'] ) && empty( $manual_v4_code ) ) {
708
- wp_send_json_error( array(
709
- 'error' => __( 'Invalid UA code', 'google-analytics-dashboard-for-wp' ),
710
- ) );
711
- }
712
-
713
- wp_send_json_success();
714
- }
715
-
716
- public function update_dual_tracking_id() {
717
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
718
-
719
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
720
- return;
721
- }
722
-
723
- if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
724
- define( 'WP_NETWORK_ADMIN', true );
725
- }
726
-
727
- $value = empty( $_REQUEST['value'] ) ? '' : sanitize_text_field( wp_unslash( $_REQUEST['value'] ) );
728
- $sanitized_ua_value = exactmetrics_is_valid_ua( $value );
729
- $sanitized_v4_value = exactmetrics_is_valid_v4_id( $value );
730
-
731
- if ( $sanitized_v4_value ) {
732
- $value = $sanitized_v4_value;
733
- } elseif ( $sanitized_ua_value ) {
734
- $value = $sanitized_ua_value;
735
- } elseif ( ! empty( $value ) ) {
736
- wp_send_json_error( array(
737
- 'error' => __( 'Invalid dual tracking code', 'google-analytics-dashboard-for-wp' ),
738
- ) );
739
- }
740
-
741
- $auth = ExactMetrics()->auth;
742
-
743
- if ( is_network_admin() ) {
744
- $auth->set_network_dual_tracking_id( $value );
745
- } else {
746
- $auth->set_dual_tracking_id( $value );
747
- }
748
-
749
- wp_send_json_success();
750
- }
751
-
752
- public function update_measurement_protocol_secret() {
753
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
754
-
755
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
756
- return;
757
- }
758
-
759
- if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
760
- define( 'WP_NETWORK_ADMIN', true );
761
- }
762
-
763
- $value = empty( $_REQUEST['value'] ) ? '' : sanitize_text_field( wp_unslash( $_REQUEST['value'] ) );
764
-
765
- $auth = ExactMetrics()->auth;
766
-
767
- if ( is_network_admin() ) {
768
- $auth->set_network_measurement_protocol_secret( $value );
769
- } else {
770
- $auth->set_measurement_protocol_secret( $value );
771
- }
772
-
773
- // Send API request to Relay
774
- // TODO: Remove when token automation API is ready
775
- $api = new ExactMetrics_API_Request( 'auth/mp-token/', 'POST' );
776
- $api->set_additional_data( array(
777
- 'mp_token' => $value,
778
- ) );
779
-
780
- // Even if there's an error from Relay, we can still return a successful json
781
- // payload because we can try again with Relay token push in the future
782
- $data = array();
783
- $result = $api->request();
784
- if ( is_wp_error( $result ) ) {
785
- // Just need to output the error in the response for debugging purpose
786
- $data['error'] = array(
787
- 'message' => $result->get_error_message(),
788
- 'code' => $result->get_error_code(),
789
- );
790
- }
791
-
792
- wp_send_json_success( $data );
793
- }
794
-
795
-
796
- /**
797
- *
798
- */
799
- public function handle_settings_import() {
800
-
801
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
802
-
803
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
804
- return;
805
- }
806
-
807
- if ( ! isset( $_FILES['import_file'] ) ) {
808
- return;
809
- }
810
-
811
- $extension = explode( '.', sanitize_text_field( wp_unslash( $_FILES['import_file']['name'] ) ) );
812
- $extension = end( $extension );
813
-
814
- if ( 'json' !== $extension ) {
815
- wp_send_json_error( array(
816
- 'message' => esc_html__( 'Please upload a valid .json file', 'google-analytics-dashboard-for-wp' ),
817
- ) );
818
- }
819
-
820
- $import_file = sanitize_text_field( wp_unslash( $_FILES['import_file']['tmp_name'] ) );
821
-
822
- $file = file_get_contents( $import_file );
823
- if ( empty( $file ) ) {
824
- wp_send_json_error( array(
825
- 'message' => esc_html__( 'Please upload a file to import', 'google-analytics-dashboard-for-wp' ),
826
- ) );
827
- }
828
-
829
- // Retrieve the settings from the file and convert the json object to an array.
830
- $new_settings = json_decode( wp_json_encode( json_decode( $file ) ), true );
831
- $settings = exactmetrics_get_options();
832
- $exclude = array(
833
- 'analytics_profile',
834
- 'analytics_profile_code',
835
- 'analytics_profile_name',
836
- 'oauth_version',
837
- 'cron_last_run',
838
- 'exactmetrics_oauth_status',
839
- );
840
-
841
- foreach ( $exclude as $e ) {
842
- if ( ! empty( $new_settings[ $e ] ) ) {
843
- unset( $new_settings[ $e ] );
844
- }
845
- }
846
-
847
- foreach ( $exclude as $e ) {
848
- if ( ! empty( $settings[ $e ] ) ) {
849
- $new_settings = $settings[ $e ];
850
- }
851
- }
852
-
853
- global $exactmetrics_settings;
854
- $exactmetrics_settings = $new_settings;
855
-
856
- update_option( exactmetrics_get_option_name(), $new_settings );
857
-
858
- wp_send_json_success( $new_settings );
859
-
860
- }
861
-
862
- /**
863
- * Generic Ajax handler for grabbing report data in JSON.
864
- */
865
- public function get_report_data() {
866
-
867
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
868
-
869
- if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
870
- wp_send_json_error( array( 'message' => __( "You don't have permission to view ExactMetrics reports.", 'google-analytics-dashboard-for-wp' ) ) );
871
- }
872
-
873
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
874
- define( 'WP_NETWORK_ADMIN', true );
875
- }
876
- $settings_page = admin_url( 'admin.php?page=exactmetrics_settings' );
877
-
878
- // Only for Pro users, require a license key to be entered first so we can link to things.
879
- if ( exactmetrics_is_pro_version() ) {
880
- if ( ! ExactMetrics()->license->is_site_licensed() && ! ExactMetrics()->license->is_network_licensed() ) {
881
- wp_send_json_error( array(
882
- 'message' => __( "You can't view ExactMetrics reports because you are not licensed.", 'google-analytics-dashboard-for-wp' ),
883
- 'footer' => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-dashboard-for-wp' ) . '</a>',
884
- ) );
885
- } else if ( ExactMetrics()->license->is_site_licensed() && ! ExactMetrics()->license->site_license_has_error() ) {
886
- // Good to go: site licensed.
887
- } else if ( ExactMetrics()->license->is_network_licensed() && ! ExactMetrics()->license->network_license_has_error() ) {
888
- // Good to go: network licensed.
889
- } else {
890
- wp_send_json_error( array( 'message' => __( "You can't view ExactMetrics reports due to license key errors.", 'google-analytics-dashboard-for-wp' ) ) );
891
- }
892
- }
893
-
894
- // We do not have a current auth.
895
- $site_auth = ExactMetrics()->auth->get_viewname();
896
- $ms_auth = is_multisite() && ExactMetrics()->auth->get_network_viewname();
897
- if ( ! $site_auth && ! $ms_auth ) {
898
- wp_send_json_error( array( 'message' => __( 'You must authenticate with ExactMetrics before you can view reports.', 'google-analytics-dashboard-for-wp' ) ) );
899
- }
900
-
901
- $report_name = isset( $_POST['report'] ) ? sanitize_text_field( wp_unslash( $_POST['report'] ) ) : '';
902
-
903
- if ( empty( $report_name ) ) {
904
- wp_send_json_error( array( 'message' => __( 'Unknown report. Try refreshing and retrying. Contact support if this issue persists.', 'google-analytics-dashboard-for-wp' ) ) );
905
- }
906
-
907
- $report = ExactMetrics()->reporting->get_report( $report_name );
908
-
909
- $isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
910
- $start = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : $report->default_start_date();
911
- $end = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : $report->default_end_date();
912
-
913
- $args = array(
914
- 'start' => $start,
915
- 'end' => $end,
916
- );
917
-
918
- if ( $isnetwork ) {
919
- $args['network'] = true;
920
- }
921
-
922
- if ( exactmetrics_is_pro_version() && ! ExactMetrics()->license->license_can( $report->level ) ) {
923
- $data = array(
924
- 'success' => false,
925
- 'error' => 'license_level',
926
- );
927
- } else {
928
- $data = apply_filters( 'exactmetrics_vue_reports_data', $report->get_data( $args ), $report_name, $report );
929
- }
930
-
931
- if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
932
- wp_send_json_success( $data['data'] );
933
- } else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
934
- // Use a custom handler for invalid_grant errors.
935
- if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
936
- wp_send_json_error(
937
- array(
938
- 'message' => 'invalid_grant',
939
- 'footer' => '',
940
- )
941
- );
942
- }
943
-
944
- wp_send_json_error(
945
- array(
946
- 'message' => $data['error'],
947
- 'footer' => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
948
- )
949
- );
950
- }
951
-
952
- wp_send_json_error( array( 'message' => __( 'We encountered an error when fetching the report data.', 'google-analytics-dashboard-for-wp' ) ) );
953
-
954
- }
955
-
956
- /**
957
- * Install plugins which are not addons.
958
- */
959
- public function install_plugin() {
960
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
961
-
962
- if ( ! exactmetrics_can_install_plugins() ) {
963
- wp_send_json( array(
964
- 'error' => esc_html__( 'You are not allowed to install plugins', 'google-analytics-dashboard-for-wp' ),
965
- ) );
966
- }
967
-
968
- $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : false;
969
-
970
- if ( ! $slug ) {
971
- wp_send_json( array(
972
- 'message' => esc_html__( 'Missing plugin name.', 'google-analytics-dashboard-for-wp' ),
973
- ) );
974
- }
975
-
976
- include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
977
-
978
- $api = plugins_api( 'plugin_information', array(
979
- 'slug' => $slug,
980
- 'fields' => array(
981
- 'short_description' => false,
982
- 'sections' => false,
983
- 'requires' => false,
984
- 'rating' => false,
985
- 'ratings' => false,
986
- 'downloaded' => false,
987
- 'last_updated' => false,
988
- 'added' => false,
989
- 'tags' => false,
990
- 'compatibility' => false,
991
- 'homepage' => false,
992
- 'donate_link' => false,
993
- ),
994
- ) );
995
-
996
- if ( is_wp_error( $api ) ) {
997
- return $api->get_error_message();
998
- }
999
-
1000
- $download_url = $api->download_link;
1001
-
1002
- $method = '';
1003
- $url = add_query_arg(
1004
- array(
1005
- 'page' => 'exactmetrics-settings',
1006
- ),
1007
- admin_url( 'admin.php' )
1008
- );
1009
- $url = esc_url( $url );
1010
-
1011
- ob_start();
1012
- if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
1013
- $form = ob_get_clean();
1014
-
1015
- wp_send_json( array( 'form' => $form ) );
1016
- }
1017
-
1018
- // If we are not authenticated, make it happen now.
1019
- if ( ! WP_Filesystem( $creds ) ) {
1020
- ob_start();
1021
- request_filesystem_credentials( $url, $method, true, false, null );
1022
- $form = ob_get_clean();
1023
-
1024
- wp_send_json( array( 'form' => $form ) );
1025
-
1026
- }
1027
-
1028
- // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
1029
- exactmetrics_require_upgrader();
1030
-
1031
- // Prevent language upgrade in ajax calls.
1032
- remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1033
- // Create the plugin upgrader with our custom skin.
1034
- $installer = new ExactMetrics_Plugin_Upgrader( new ExactMetrics_Skin() );
1035
- $installer->install( $download_url );
1036
-
1037
- // Flush the cache and return the newly installed plugin basename.
1038
- wp_cache_flush();
1039
- wp_send_json_success();
1040
-
1041
- wp_die();
1042
- }
1043
-
1044
- /**
1045
- * Store that the first run notice has been dismissed so it doesn't show up again.
1046
- */
1047
- public function dismiss_first_time_notice() {
1048
-
1049
- exactmetrics_update_option( 'exactmetrics_first_run_notice', true );
1050
-
1051
- wp_send_json_success();
1052
- }
1053
-
1054
- /**
1055
- * Get the notice status by id.
1056
- */
1057
- public function get_notice_status() {
1058
-
1059
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1060
-
1061
- $notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
1062
- if ( ! $notice_id ) {
1063
- wp_send_json_error();
1064
- }
1065
- $is_dismissed = ExactMetrics()->notices->is_dismissed( $notice_id );
1066
-
1067
- wp_send_json_success( array(
1068
- 'dismissed' => $is_dismissed,
1069
- ) );
1070
- }
1071
-
1072
- /**
1073
- * Dismiss notices by id.
1074
- */
1075
- public function dismiss_notice() {
1076
-
1077
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1078
-
1079
- $notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
1080
- if ( ! $notice_id ) {
1081
- wp_send_json_error();
1082
- }
1083
- ExactMetrics()->notices->dismiss( $notice_id );
1084
-
1085
- wp_send_json_success();
1086
- }
1087
-
1088
- /**
1089
- * Retrieve posts/pages
1090
- *
1091
- * @access admin
1092
- * @since 3.0.0
1093
- */
1094
- public function get_posts() {
1095
-
1096
- // Run a security check first.
1097
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1098
-
1099
- $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( wp_unslash( $_POST['post_type'] ) ) : 'any';
1100
-
1101
- $args = array(
1102
- 's' => isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '',
1103
- 'post_type' => $post_type,
1104
- 'posts_per_page' => isset( $_POST['numberposts'] ) ? sanitize_text_field( wp_unslash( $_POST['numberposts'] ) ) : 10,
1105
- 'orderby' => 'relevance',
1106
- );
1107
-
1108
- $array = array();
1109
- $posts = get_posts( $args );
1110
-
1111
- if ( in_array( $post_type, array( 'page', 'any' ), true ) ) {
1112
- $homepage = get_option( 'page_on_front' );
1113
- if ( ! $homepage ) {
1114
- $array[] = array(
1115
- 'id' => - 1,
1116
- 'title' => __( 'Homepage', 'google-analytics-dashboard-for-wp' ),
1117
- );
1118
- }
1119
- }
1120
-
1121
- if ( $posts ) {
1122
- foreach ( $posts as $post ) {
1123
- $array[] = array(
1124
- 'id' => $post->ID,
1125
- 'title' => $post->post_title,
1126
- );
1127
- }
1128
- }
1129
-
1130
- wp_send_json_success( $array );
1131
- }
1132
-
1133
- /**
1134
- * Search for taxonomy terms.
1135
- *
1136
- * @access admin
1137
- * @since 3.0.0
1138
- */
1139
- public function get_taxonomy_terms() {
1140
-
1141
- // Run a security check first.
1142
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1143
-
1144
- $keyword = isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '';
1145
- $taxonomy = isset( $_POST['taxonomy'] ) ? sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) ) : 'category';
1146
-
1147
- $args = array(
1148
- 'taxonomy' => array( $taxonomy ),
1149
- 'hide_empty' => false,
1150
- 'name__like' => $keyword,
1151
- );
1152
-
1153
- $terms = get_terms( $args );
1154
- $array = array();
1155
-
1156
- if ( ! empty( $terms ) ) {
1157
- foreach ( $terms as $term ) {
1158
- $array[] = array(
1159
- 'id' => esc_attr( $term->term_id ),
1160
- 'text' => esc_attr( $term->name ),
1161
- );
1162
- }
1163
- }
1164
-
1165
- wp_send_json_success( $array );
1166
- }
1167
-
1168
- /**
1169
- * Get the post types in a name => Label array.
1170
- */
1171
- public function get_post_types() {
1172
-
1173
- // Run a security check first.
1174
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1175
-
1176
- $post_types_args = array(
1177
- 'public' => true,
1178
- );
1179
- $post_types = get_post_types( $post_types_args, 'objects' );
1180
-
1181
- $post_types_parsed = array();
1182
-
1183
- foreach ( $post_types as $post_type ) {
1184
- // Exclude post types that don't support the content editor.
1185
- // Exclude the WooCommerce product post type as that doesn't use the "the_content" filter and we can't auto-add popular posts to it.
1186
- if ( ! post_type_supports( $post_type->name, 'editor' ) || 'product' === $post_type->name ) {
1187
- continue;
1188
- }
1189
- $post_types_parsed[ $post_type->name ] = $post_type->labels->singular_name;
1190
- }
1191
-
1192
- $post_types_parsed = apply_filters( 'exactmetrics_vue_post_types_editor', $post_types_parsed );
1193
-
1194
- wp_send_json( $post_types_parsed );
1195
-
1196
- }
1197
-
1198
-
1199
- public function check_popular_posts_report() {
1200
-
1201
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1202
-
1203
- if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
1204
- wp_send_json_error( array( 'message' => __( "You don't have permission to view ExactMetrics reports.", 'google-analytics-dashboard-for-wp' ) ) );
1205
- }
1206
-
1207
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
1208
- define( 'WP_NETWORK_ADMIN', true );
1209
- }
1210
- $settings_page = admin_url( 'admin.php?page=exactmetrics_settings' );
1211
-
1212
- // Only for Pro users, require a license key to be entered first so we can link to things.
1213
- if ( exactmetrics_is_pro_version() ) {
1214
- if ( ! ExactMetrics()->license->is_site_licensed() && ! ExactMetrics()->license->is_network_licensed() ) {
1215
- wp_send_json_error( array(
1216
- 'message' => __( "You can't view ExactMetrics reports because you are not licensed.", 'google-analytics-dashboard-for-wp' ),
1217
- 'footer' => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-dashboard-for-wp' ) . '</a>',
1218
- ) );
1219
- } else if ( ExactMetrics()->license->is_site_licensed() && ! ExactMetrics()->license->site_license_has_error() ) {
1220
- // Good to go: site licensed.
1221
- } else if ( ExactMetrics()->license->is_network_licensed() && ! ExactMetrics()->license->network_license_has_error() ) {
1222
- // Good to go: network licensed.
1223
- } else {
1224
- wp_send_json_error( array( 'message' => __( 'You can\'t view ExactMetrics reports due to license key errors.', 'google-analytics-dashboard-for-wp' ) ) );
1225
- }
1226
- }
1227
-
1228
- // We do not have a current auth.
1229
- $site_auth = ExactMetrics()->auth->get_viewname();
1230
- $ms_auth = is_multisite() && ExactMetrics()->auth->get_network_viewname();
1231
- if ( ! $site_auth && ! $ms_auth ) {
1232
- wp_send_json_error( array( 'message' => __( 'You must authenticate with ExactMetrics before you can view reports.', 'google-analytics-dashboard-for-wp' ) ) );
1233
- }
1234
-
1235
- $report_name = 'popularposts';
1236
-
1237
- if ( empty( $report_name ) ) {
1238
- wp_send_json_error( array( 'message' => __( 'Unknown report. Try refreshing and retrying. Contact support if this issue persists.', 'google-analytics-dashboard-for-wp' ) ) );
1239
- }
1240
-
1241
- $report = ExactMetrics()->reporting->get_report( $report_name );
1242
-
1243
- $isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
1244
- $start = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : $report->default_start_date();
1245
- $end = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : $report->default_end_date();
1246
-
1247
- $args = array(
1248
- 'start' => $start,
1249
- 'end' => $end,
1250
- );
1251
-
1252
- if ( $isnetwork ) {
1253
- $args['network'] = true;
1254
- }
1255
-
1256
- if ( exactmetrics_is_pro_version() && ! ExactMetrics()->license->license_can( $report->level ) ) {
1257
- $data = array(
1258
- 'success' => false,
1259
- 'error' => 'license_level',
1260
- );
1261
- } else {
1262
- $data = apply_filters( 'exactmetrics_vue_reports_data', $report->get_data( $args ), $report_name, $report );
1263
- }
1264
-
1265
- if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
1266
- wp_send_json_success( $data['data'] );
1267
- } else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
1268
- // Use a custom handler for invalid_grant errors.
1269
- if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
1270
- wp_send_json_error(
1271
- array(
1272
- 'message' => 'invalid_grant',
1273
- 'footer' => '',
1274
- )
1275
- );
1276
- }
1277
-
1278
- wp_send_json_error(
1279
- array(
1280
- 'message' => $data['error'],
1281
- 'footer' => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
1282
- )
1283
- );
1284
- }
1285
-
1286
- wp_send_json_error( array( 'message' => __( 'We encountered an error when fetching the report data.', 'google-analytics-dashboard-for-wp' ) ) );
1287
-
1288
- }
1289
-
1290
- /**
1291
- * Ajax handler for popular posts theme customization settings.
1292
- * Specific theme styles are stored separately so we can handle 20+ themes with their specific settings.
1293
- */
1294
- public function update_popular_posts_theme_setting() {
1295
-
1296
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1297
-
1298
- if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
1299
- return;
1300
- }
1301
-
1302
- if ( ! empty( $_POST['type'] ) && ! empty( $_POST['theme'] ) && ! empty( $_POST['object'] ) && ! empty( $_POST['key'] ) && ! empty( $_POST['value'] ) ) {
1303
- $settings_key = 'exactmetrics_popular_posts_theme_settings';
1304
- $type = sanitize_text_field( wp_unslash( $_POST['type'] ) ); // Type of Popular Posts instance: inline/widget/products.
1305
- $theme = sanitize_text_field( wp_unslash( $_POST['theme'] ) );
1306
- $object = sanitize_text_field( wp_unslash( $_POST['object'] ) ); // Style object like title, label, background, etc.
1307
- $key = sanitize_text_field( wp_unslash( $_POST['key'] ) ); // Style key for the object like color, font size, etc.
1308
- $value = sanitize_text_field( wp_unslash( $_POST['value'] ) ); // Value of custom style like 12px or #fff.
1309
- $settings = get_option( $settings_key, array() );
1310
-
1311
- if ( ! isset( $settings[ $type ] ) ) {
1312
- $settings[ $type ] = array();
1313
- }
1314
- if ( ! isset( $settings[ $type ][ $theme ] ) ) {
1315
- $settings[ $type ][ $theme ] = array();
1316
- }
1317
-
1318
- if ( ! isset( $settings[ $type ][ $theme ][ $object ] ) ) {
1319
- $settings[ $type ][ $theme ][ $object ] = array();
1320
- }
1321
-
1322
- $settings[ $type ][ $theme ][ $object ][ $key ] = $value;
1323
-
1324
- update_option( $settings_key, $settings );
1325
-
1326
- wp_send_json_success();
1327
- }
1328
-
1329
- wp_send_json_error();
1330
-
1331
- }
1332
- }
 
 
 
1
+ <?php
2
+ /**
3
+ * Routes for VUE are registered here.
4
+ *
5
+ * @package exactmetrics
6
+ */
7
+
8
+ /**
9
+ * Class ExactMetrics_Rest_Routes
10
+ */
11
+ class ExactMetrics_Rest_Routes {
12
+
13
+ /**
14
+ * ExactMetrics_Rest_Routes constructor.
15
+ */
16
+ public function __construct() {
17
+
18
+ add_action( 'wp_ajax_exactmetrics_vue_get_license', array( $this, 'get_license' ) );
19
+ add_action( 'wp_ajax_exactmetrics_vue_get_profile', array( $this, 'get_profile' ) );
20
+ add_action( 'wp_ajax_exactmetrics_vue_get_settings', array( $this, 'get_settings' ) );
21
+ add_action( 'wp_ajax_exactmetrics_vue_update_settings', array( $this, 'update_settings' ) );
22
+ add_action( 'wp_ajax_exactmetrics_vue_update_settings_bulk', array( $this, 'update_settings_bulk' ) );
23
+ add_action( 'wp_ajax_exactmetrics_vue_get_addons', array( $this, 'get_addons' ) );
24
+ add_action( 'wp_ajax_exactmetrics_update_manual_ua', array( $this, 'update_manual_ua' ) );
25
+ add_action( 'wp_ajax_exactmetrics_update_manual_v4', array( $this, 'update_manual_v4' ) );
26
+ add_action( 'wp_ajax_exactmetrics_update_dual_tracking_id', array( $this, 'update_dual_tracking_id' ) );
27
+ add_action( 'wp_ajax_exactmetrics_update_measurement_protocol_secret', array( $this, 'update_measurement_protocol_secret' ) );
28
+ add_action( 'wp_ajax_exactmetrics_vue_get_report_data', array( $this, 'get_report_data' ) );
29
+ add_action( 'wp_ajax_exactmetrics_vue_install_plugin', array( $this, 'install_plugin' ) );
30
+ add_action( 'wp_ajax_exactmetrics_vue_notice_status', array( $this, 'get_notice_status' ) );
31
+ add_action( 'wp_ajax_exactmetrics_vue_notice_dismiss', array( $this, 'dismiss_notice' ) );
32
+ add_action( 'wp_ajax_exactmetrics_vue_grab_popular_posts_report', array(
33
+ $this,
34
+ 'check_popular_posts_report'
35
+ ) );
36
+ add_action( 'wp_ajax_exactmetrics_vue_popular_posts_update_theme_setting', array(
37
+ $this,
38
+ 'update_popular_posts_theme_setting'
39
+ ) );
40
+
41
+ // TODO: remove function from Google Optimize Addon.
42
+ add_action( 'wp_ajax_exactmetrics_get_posts', array( $this, 'get_posts' ) );
43
+
44
+ // Search for taxonomies.
45
+ add_action( 'wp_ajax_exactmetrics_get_terms', array( $this, 'get_taxonomy_terms' ) );
46
+
47
+ add_action( 'wp_ajax_exactmetrics_get_post_types', array( $this, 'get_post_types' ) );
48
+
49
+ add_action( 'wp_ajax_exactmetrics_handle_settings_import', array( $this, 'handle_settings_import' ) );
50
+
51
+ add_action( 'admin_notices', array( $this, 'hide_old_notices' ), 0 );
52
+
53
+ add_action( 'wp_ajax_exactmetrics_vue_dismiss_first_time_notice', array(
54
+ $this,
55
+ 'dismiss_first_time_notice'
56
+ ) );
57
+ }
58
+
59
+ /**
60
+ * Ajax handler for grabbing the license
61
+ */
62
+ public function get_license() {
63
+
64
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
65
+
66
+ if ( ! current_user_can( 'exactmetrics_view_dashboard' ) || ! exactmetrics_is_pro_version() ) {
67
+ return;
68
+ }
69
+
70
+ $site_license = array(
71
+ 'key' => ExactMetrics()->license->get_site_license_key(),
72
+ 'type' => ExactMetrics()->license->get_site_license_type(),
73
+ 'is_disabled' => ExactMetrics()->license->site_license_disabled(),
74
+ 'is_expired' => ExactMetrics()->license->site_license_expired(),
75
+ 'is_invalid' => ExactMetrics()->license->site_license_invalid(),
76
+ );
77
+ $network_license = array(
78
+ 'key' => ExactMetrics()->license->get_network_license_key(),
79
+ 'type' => ExactMetrics()->license->get_network_license_type(),
80
+ 'is_disabled' => ExactMetrics()->license->network_license_disabled(),
81
+ 'is_expired' => ExactMetrics()->license->network_license_expired(),
82
+ 'is_invalid' => ExactMetrics()->license->network_license_disabled(),
83
+ );
84
+
85
+ wp_send_json( array(
86
+ 'site' => $site_license,
87
+ 'network' => $network_license,
88
+ ) );
89
+
90
+ }
91
+
92
+ /**
93
+ * Ajax handler for grabbing the current authenticated profile.
94
+ */
95
+ public function get_profile() {
96
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
97
+
98
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
99
+ return;
100
+ }
101
+
102
+ $auth = ExactMetrics()->auth;
103
+
104
+ wp_send_json( array(
105
+ 'ua' => $auth->get_ua(),
106
+ 'v4' => $auth->get_v4_id(),
107
+ 'viewname' => $auth->get_viewname(),
108
+ 'manual_ua' => $auth->get_manual_ua(),
109
+ 'manual_v4' => $auth->get_manual_v4_id(),
110
+ 'measurement_protocol_secret' => $auth->get_measurement_protocol_secret(),
111
+ 'network_ua' => $auth->get_network_ua(),
112
+ 'network_v4' => $auth->get_network_v4_id(),
113
+ 'network_viewname' => $auth->get_network_viewname(),
114
+ 'network_manual_ua' => $auth->get_network_manual_ua(),
115
+ 'network_manual_v4' => $auth->get_network_manual_v4_id(),
116
+ 'network_measurement_protocol_secret' => $auth->get_network_measurement_protocol_secret(),
117
+ 'connected_type' => $auth->get_connected_type(),
118
+ ) );
119
+
120
+ }
121
+
122
+ /**
123
+ * Ajax handler for grabbing the settings.
124
+ */
125
+ public function get_settings() {
126
+
127
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
128
+
129
+ if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
130
+ return;
131
+ }
132
+
133
+ $options = exactmetrics_get_options();
134
+
135
+ // Array fields are needed even if empty.
136
+ $array_fields = array( 'view_reports', 'save_settings', 'ignore_users' );
137
+ foreach ( $array_fields as $array_field ) {
138
+ if ( ! isset( $options[ $array_field ] ) ) {
139
+ $options[ $array_field ] = array();
140
+ }
141
+ }
142
+
143
+ //add email summaries options
144
+ if ( exactmetrics_is_pro_version() ) {
145
+ $default_email = array(
146
+ 'email' => get_option( 'admin_email' ),
147
+ );
148
+
149
+ if ( ! isset( $options['email_summaries'] ) ) {
150
+ $options['email_summaries'] = 'on';
151
+ }
152
+
153
+ if ( ! isset( $options['summaries_email_addresses'] ) ) {
154
+ $options['summaries_email_addresses'] = array(
155
+ $default_email,
156
+ );
157
+ }
158
+
159
+ if ( ! isset( $options['summaries_html_template'] ) ) {
160
+ $options['summaries_html_template'] = 'yes';
161
+ }
162
+
163
+
164
+ if ( ! isset( $options['summaries_carbon_copy'] ) ) {
165
+ $options['summaries_carbon_copy'] = 'no';
166
+ }
167
+
168
+
169
+ if ( ! isset( $options['summaries_header_image'] ) ) {
170
+ $options['summaries_header_image'] = '';
171
+ }
172
+
173
+ if ( ! isset( $options['local_gtag_file_modified_at'] ) ) {
174
+ $options['local_gtag_file_modified_at'] = '';
175
+ }
176
+ }
177
+
178
+ wp_send_json( $options );
179
+
180
+ }
181
+
182
+ /**
183
+ * Ajax handler for updating the settings.
184
+ */
185
+ public function update_settings() {
186
+
187
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
188
+
189
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
190
+ return;
191
+ }
192
+
193
+ if ( isset( $_POST['setting'] ) ) {
194
+ $setting = sanitize_text_field( wp_unslash( $_POST['setting'] ) );
195
+ if ( isset( $_POST['value'] ) ) {
196
+ $value = $this->handle_sanitization( $setting, $_POST['value'] );
197
+ exactmetrics_update_option( $setting, $value );
198
+ do_action( 'exactmetrics_after_update_settings', $setting, $value );
199
+ } else {
200
+ exactmetrics_update_option( $setting, false );
201
+ do_action( 'exactmetrics_after_update_settings', $setting, false );
202
+ }
203
+ }
204
+
205
+ wp_send_json_success();
206
+
207
+ }
208
+
209
+ /**
210
+ * Ajax handler for updating the settings.
211
+ */
212
+ public function update_settings_bulk() {
213
+
214
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
215
+
216
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
217
+ return;
218
+ }
219
+
220
+ if ( isset( $_POST['settings'] ) ) {
221
+ $settings = json_decode( sanitize_text_field( wp_unslash( $_POST['settings'] ) ), true );
222
+ foreach ( $settings as $setting => $value ) {
223
+ $value = $this->handle_sanitization( $setting, $value );
224
+ exactmetrics_update_option( $setting, $value );
225
+ do_action( 'exactmetrics_after_update_settings', $setting, $value );
226
+ }
227
+ }
228
+
229
+ wp_send_json_success();
230
+
231
+ }
232
+
233
+ /**
234
+ * Sanitization specific to each field.
235
+ *
236
+ * @param string $field The key of the field to sanitize.
237
+ * @param string $value The value of the field to sanitize.
238
+ *
239
+ * @return mixed The sanitized input.
240
+ */
241
+ private function handle_sanitization( $field, $value ) {
242
+
243
+ $value = wp_unslash( $value );
244
+
245
+ // Textarea fields.
246
+ $textarea_fields = array();
247
+
248
+ if ( in_array( $field, $textarea_fields, true ) ) {
249
+ if ( function_exists( 'sanitize_textarea_field' ) ) {
250
+ return sanitize_textarea_field( $value );
251
+ } else {
252
+ return wp_kses( $value, array() );
253
+ }
254
+ }
255
+
256
+ $array_value = json_decode( $value, true );
257
+ if ( is_array( $array_value ) ) {
258
+ $value = $array_value;
259
+ // Don't save empty values.
260
+ foreach ( $value as $key => $item ) {
261
+ if ( is_array( $item ) ) {
262
+ $empty = true;
263
+ foreach ( $item as $item_value ) {
264
+ if ( ! empty( $item_value ) ) {
265
+ $empty = false;
266
+ }
267
+ }
268
+ if ( $empty ) {
269
+ unset( $value[ $key ] );
270
+ }
271
+ }
272
+ }
273
+
274
+ // Reset array keys because JavaScript can't handle arrays with non-sequential keys.
275
+ $value = array_values( $value );
276
+
277
+ return $value;
278
+ }
279
+
280
+ return sanitize_text_field( $value );
281
+
282
+ }
283
+
284
+ /**
285
+ * Return the state of the addons ( installed, activated )
286
+ */
287
+ public function get_addons() {
288
+
289
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
290
+
291
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
292
+ return;
293
+ }
294
+
295
+ if ( isset( $_POST['network'] ) && intval( $_POST['network'] ) > 0 ) {
296
+ define( 'WP_NETWORK_ADMIN', true );
297
+ }
298
+
299
+ $addons_data = exactmetrics_get_addons();
300
+ $parsed_addons = array();
301
+ $installed_plugins = get_plugins();
302
+
303
+ if ( ! is_array( $addons_data ) ) {
304
+ $addons_data = array();
305
+ }
306
+
307
+ foreach ( $addons_data as $addons_type => $addons ) {
308
+ foreach ( $addons as $addon ) {
309
+ $slug = 'exactmetrics-' . $addon->slug;
310
+ if ( 'exactmetrics-ecommerce' === $slug && 'm' === $slug[0] ) {
311
+ $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
312
+ if ( empty( $addon->installed ) ) {
313
+ $slug = 'ga-ecommerce';
314
+ $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
315
+ }
316
+ } else {
317
+ $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
318
+ }
319
+ $parsed_addons[ $addon->slug ] = $addon;
320
+ }
321
+ }
322
+
323
+ // Include data about the plugins needed by some addons ( WooCommerce, EDD, Google AMP, CookieBot, etc ).
324
+ // WooCommerce.
325
+ $parsed_addons['woocommerce'] = array(
326
+ 'active' => class_exists( 'WooCommerce' ),
327
+ );
328
+ // Edd.
329
+ $parsed_addons['easy_digital_downloads'] = array(
330
+ 'active' => class_exists( 'Easy_Digital_Downloads' ),
331
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-edd.png',
332
+ 'title' => 'Easy Digital Downloads',
333
+ 'excerpt' => __( 'Easy digital downloads plugin.', 'google-analytics-dashboard-for-wp' ),
334
+ 'installed' => array_key_exists( 'easy-digital-downloads/easy-digital-downloads.php', $installed_plugins ),
335
+ 'basename' => 'easy-digital-downloads/easy-digital-downloads.php',
336
+ 'slug' => 'easy-digital-downloads',
337
+ 'settings' => admin_url( 'edit.php?post_type=download' ),
338
+ );
339
+ // MemberPress.
340
+ $parsed_addons['memberpress'] = array(
341
+ 'active' => defined( 'MEPR_VERSION' ) && version_compare( MEPR_VERSION, '1.3.43', '>' ),
342
+ );
343
+ // LifterLMS.
344
+ $parsed_addons['lifterlms'] = array(
345
+ 'active' => function_exists( 'LLMS' ) && version_compare( LLMS()->version, '3.32.0', '>=' ),
346
+ );
347
+ // Restrict Content Pro.
348
+ $parsed_addons['rcp'] = array(
349
+ 'active' => class_exists( 'Restrict_Content_Pro' ) && version_compare( RCP_PLUGIN_VERSION, '3.5.4', '>=' ),
350
+ );
351
+ // GiveWP.
352
+ $parsed_addons['givewp'] = array(
353
+ 'active' => function_exists( 'Give' ),
354
+ );
355
+ // GiveWP Analytics.
356
+ $parsed_addons['givewp_google_analytics'] = array(
357
+ 'active' => function_exists( 'Give_Google_Analytics' ),
358
+ );
359
+ // Cookiebot.
360
+ $parsed_addons['cookiebot'] = array(
361
+ 'active' => function_exists( 'cookiebot_active' ) && cookiebot_active(),
362
+ );
363
+ // Cookie Notice.
364
+ $parsed_addons['cookie_notice'] = array(
365
+ 'active' => class_exists( 'Cookie_Notice' ),
366
+ );
367
+ // Complianz.
368
+ $parsed_addons['complianz'] = array(
369
+ 'active' => defined( 'cmplz_plugin') || defined( 'cmplz_premium'),
370
+ );
371
+ // Cookie Yes
372
+ $parsed_addons['cookie_yes'] = array(
373
+ 'active' => defined( 'CLI_SETTINGS_FIELD'),
374
+ );
375
+ // Fb Instant Articles.
376
+ $parsed_addons['instant_articles'] = array(
377
+ 'active' => defined( 'IA_PLUGIN_VERSION' ) && version_compare( IA_PLUGIN_VERSION, '3.3.4', '>' ),
378
+ );
379
+ // Google AMP.
380
+ $parsed_addons['google_amp'] = array(
381
+ 'active' => defined( 'AMP__FILE__' ),
382
+ );
383
+ // Yoast SEO.
384
+ $parsed_addons['yoast_seo'] = array(
385
+ 'active' => defined( 'WPSEO_VERSION' ),
386
+ );
387
+ // EasyAffiliate.
388
+ $parsed_addons['easy_affiliate'] = array(
389
+ 'active' => defined( 'ESAF_EDITION' ),
390
+ );
391
+ $parsed_addons['affiliate_wp'] = array(
392
+ 'active' => function_exists( 'affiliate_wp' ) && defined( 'AFFILIATEWP_VERSION' ),
393
+ );
394
+ // WPForms.
395
+ $parsed_addons['wpforms-lite'] = array(
396
+ 'active' => function_exists( 'wpforms' ),
397
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-wpforms.png',
398
+ 'title' => 'WPForms',
399
+ 'excerpt' => __( 'The best drag & drop WordPress form builder. Easily create beautiful contact forms, surveys, payment forms, and more with our 150+ form templates. Trusted by over 4 million websites as the best forms plugin', 'google-analytics-dashboard-for-wp' ),
400
+ 'installed' => array_key_exists( 'wpforms-lite/wpforms.php', $installed_plugins ),
401
+ 'basename' => 'wpforms-lite/wpforms.php',
402
+ 'slug' => 'wpforms-lite',
403
+ 'settings' => admin_url( 'admin.php?page=wpforms-overview' ),
404
+ );
405
+ // AIOSEO.
406
+ $parsed_addons['aioseo'] = array(
407
+ 'active' => function_exists( 'aioseo' ),
408
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-all-in-one-seo.png',
409
+ 'title' => 'AIOSEO',
410
+ 'excerpt' => __( 'The original WordPress SEO plugin and toolkit that improves your website’s search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.', 'google-analytics-dashboard-for-wp' ),
411
+ 'installed' => array_key_exists( 'all-in-one-seo-pack/all_in_one_seo_pack.php', $installed_plugins ),
412
+ 'basename' => ( exactmetrics_is_installed_aioseo_pro() ) ? 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php' : 'all-in-one-seo-pack/all_in_one_seo_pack.php',
413
+ 'slug' => 'all-in-one-seo-pack',
414
+ 'settings' => admin_url( 'admin.php?page=aioseo' ),
415
+ );
416
+ // OptinMonster.
417
+ $parsed_addons['optinmonster'] = array(
418
+ 'active' => class_exists( 'OMAPI' ),
419
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-om.png',
420
+ 'title' => 'OptinMonster',
421
+ 'excerpt' => __( 'Instantly get more subscribers, leads, and sales with the #1 conversion optimization toolkit. Create high converting popups, announcement bars, spin a wheel, and more with smart targeting and personalization.', 'google-analytics-dashboard-for-wp' ),
422
+ 'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
423
+ 'basename' => 'optinmonster/optin-monster-wp-api.php',
424
+ 'slug' => 'optinmonster',
425
+ 'settings' => admin_url( 'admin.php?page=optin-monster-dashboard' ),
426
+ );
427
+ // WP Mail Smtp.
428
+ $parsed_addons['wp-mail-smtp'] = array(
429
+ 'active' => function_exists( 'wp_mail_smtp' ),
430
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-smtp.png',
431
+ 'title' => 'WP Mail SMTP',
432
+ 'excerpt' => __( 'Improve your WordPress email deliverability and make sure that your website emails reach user’s inbox with the #1 SMTP plugin for WordPress. Over 2 million websites use it to fix WordPress email issues.', 'google-analytics-dashboard-for-wp' ),
433
+ 'installed' => array_key_exists( 'wp-mail-smtp/wp_mail_smtp.php', $installed_plugins ),
434
+ 'basename' => 'wp-mail-smtp/wp_mail_smtp.php',
435
+ 'slug' => 'wp-mail-smtp',
436
+ );
437
+ // SeedProd.
438
+ $parsed_addons['coming-soon'] = array(
439
+ 'active' => defined( 'SEEDPROD_VERSION' ),
440
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-seedprod.png',
441
+ 'title' => 'SeedProd',
442
+ 'excerpt' => __( 'The fastest drag & drop landing page builder for WordPress. Create custom landing pages without writing code, connect them with your CRM, collect subscribers, and grow your audience. Trusted by 1 million sites.', 'google-analytics-dashboard-for-wp' ),
443
+ 'installed' => array_key_exists( 'coming-soon/coming-soon.php', $installed_plugins ),
444
+ 'basename' => 'coming-soon/coming-soon.php',
445
+ 'slug' => 'coming-soon',
446
+ 'settings' => admin_url( 'admin.php?page=seedprod_lite' ),
447
+ );
448
+ // RafflePress
449
+ $parsed_addons['rafflepress'] = array(
450
+ 'active' => function_exists( 'rafflepress_lite_activation' ),
451
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/pluign-rafflepress.png',
452
+ 'title' => 'RafflePress',
453
+ 'excerpt' => __( 'Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.', 'google-analytics-dashboard-for-wp' ),
454
+ 'installed' => array_key_exists( 'rafflepress/rafflepress.php', $installed_plugins ),
455
+ 'basename' => 'rafflepress/rafflepress.php',
456
+ 'slug' => 'rafflepress',
457
+ 'settings' => admin_url( 'admin.php?page=rafflepress_lite' ),
458
+ );
459
+ // TrustPulse
460
+ $parsed_addons['trustpulse-api'] = array(
461
+ 'active' => class_exists( 'TPAPI' ),
462
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-trust-pulse.png',
463
+ 'title' => 'TrustPulse',
464
+ 'excerpt' => __( 'Boost your sales and conversions by up to 15% with real-time social proof notifications. TrustPulse helps you show live user activity and purchases to help convince other users to purchase.', 'google-analytics-dashboard-for-wp' ),
465
+ 'installed' => array_key_exists( 'trustpulse-api/trustpulse.php', $installed_plugins ),
466
+ 'basename' => 'trustpulse-api/trustpulse.php',
467
+ 'slug' => 'trustpulse-api',
468
+ );
469
+ // Smash Balloon (Instagram)
470
+ $parsed_addons['smash-balloon-instagram'] = array(
471
+ 'active' => defined( 'SBIVER' ),
472
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-smash-balloon.png',
473
+ 'title' => 'Smash Balloon Instagram Feeds',
474
+ 'excerpt' => __( 'Easily display Instagram content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'google-analytics-dashboard-for-wp' ),
475
+ 'installed' => array_key_exists( 'instagram-feed/instagram-feed.php', $installed_plugins ),
476
+ 'basename' => 'instagram-feed/instagram-feed.php',
477
+ 'slug' => 'instagram-feed',
478
+ 'settings' => admin_url( 'admin.php?page=sb-instagram-feed' ),
479
+ );
480
+ // Smash Balloon (Facebook)
481
+ $parsed_addons['smash-balloon-facebook'] = array(
482
+ 'active' => defined( 'CFFVER' ),
483
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-smash-balloon.png',
484
+ 'title' => 'Smash Balloon Facebook Feeds',
485
+ 'excerpt' => __( 'Easily display Facebook content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'google-analytics-dashboard-for-wp' ),
486
+ 'installed' => array_key_exists( 'custom-facebook-feed/custom-facebook-feed.php', $installed_plugins ),
487
+ 'basename' => 'custom-facebook-feed/custom-facebook-feed.php',
488
+ 'slug' => 'custom-facebook-feed',
489
+ 'settings' => admin_url( 'admin.php?page=cff-feed-builder' ),
490
+ );
491
+ // PushEngage
492
+ $parsed_addons['pushengage'] = array(
493
+ 'active' => method_exists( 'Pushengage', 'init' ),
494
+ 'icon' => plugin_dir_url( EXACTMETRICS_PLUGIN_FILE ) . 'assets/images/plugin-pushengage.svg',
495
+ 'title' => 'PushEngage',
496
+ 'excerpt' => __( 'Connect with your visitors after they leave your website with the leading web push notification software. Over 10,000+ businesses worldwide use PushEngage to send 9 billion notifications each month.', 'google-analytics-dashboard-for-wp' ),
497
+ 'installed' => array_key_exists( 'pushengage/main.php', $installed_plugins ),
498
+ 'basename' => 'pushengage/main.php',
499
+ 'slug' => 'pushengage',
500
+ );
501
+ // Pretty Links
502
+ $parsed_addons['pretty-link'] = array(
503
+ 'active' => class_exists( 'PrliBaseController' ),
504
+ 'icon' => '',
505
+ 'title' => 'Pretty Links',
506
+ 'excerpt' => __( 'Pretty Links helps you shrink, beautify, track, manage and share any URL on or off of your WordPress website. Create links that look how you want using your own domain name!', 'google-analytics-dashboard-for-wp' ),
507
+ 'installed' => array_key_exists( 'pretty-link/pretty-link.php', $installed_plugins ),
508
+ 'basename' => 'pretty-link/pretty-link.php',
509
+ 'slug' => 'pretty-link',
510
+ 'settings' => admin_url( 'edit.php?post_type=pretty-link' ),
511
+ );
512
+ // Thirsty Affiliates
513
+ $parsed_addons['thirstyaffiliates'] = array(
514
+ 'active' => class_exists( 'ThirstyAffiliates' ),
515
+ 'icon' => '',
516
+ 'title' => 'Thirsty Affiliates',
517
+ 'excerpt' => __( 'ThirstyAffiliates is a revolution in affiliate link management. Collect, collate and store your affiliate links for use in your posts and pages.', 'google-analytics-dashboard-for-wp' ),
518
+ 'installed' => array_key_exists( 'thirstyaffiliates/thirstyaffiliates.php', $installed_plugins ),
519
+ 'basename' => 'thirstyaffiliates/thirstyaffiliates.php',
520
+ 'slug' => 'thirstyaffiliates',
521
+ 'settings' => admin_url( 'edit.php?post_type=thirstylink' ),
522
+ );
523
+ if ( function_exists( 'WC' ) ) {
524
+ // Advanced Coupons
525
+ $parsed_addons['advancedcoupons'] = array(
526
+ 'active' => class_exists( 'ACFWF' ),
527
+ 'icon' => '',
528
+ 'title' => 'Advanced Coupons',
529
+ 'excerpt' => __( 'Advanced Coupons for WooCommerce (Free Version) gives WooCommerce store owners extra coupon features so they can market their stores better.', 'google-analytics-dashboard-for-wp' ),
530
+ 'installed' => array_key_exists( 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php', $installed_plugins ),
531
+ 'basename' => 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php',
532
+ 'slug' => 'advanced-coupons-for-woocommerce-free',
533
+ 'settings' => admin_url( 'edit.php?post_type=shop_coupon&acfw' ),
534
+ );
535
+ }
536
+ // Gravity Forms.
537
+ $parsed_addons['gravity_forms'] = array(
538
+ 'active' => class_exists( 'GFCommon' ),
539
+ );
540
+ // Formidable Forms.
541
+ $parsed_addons['formidable_forms'] = array(
542
+ 'active' => class_exists( 'FrmHooksController' ),
543
+ );
544
+ // Manual UA Addon.
545
+ if ( ! isset( $parsed_addons['manual_ua'] ) ) {
546
+ $parsed_addons['manual_ua'] = array(
547
+ 'active' => class_exists( 'ExactMetrics_Manual_UA' ),
548
+ );
549
+ }
550
+
551
+ wp_send_json( $parsed_addons );
552
+ }
553
+
554
+ public function get_addon( $installed_plugins, $addons_type, $addon, $slug ) {
555
+ $active = false;
556
+ $installed = false;
557
+ $plugin_basename = exactmetrics_get_plugin_basename_from_slug( $slug );
558
+
559
+ if ( isset( $installed_plugins[ $plugin_basename ] ) ) {
560
+ $installed = true;
561
+
562
+ if ( is_multisite() && is_network_admin() ) {
563
+ $active = is_plugin_active_for_network( $plugin_basename );
564
+ } else {
565
+ $active = is_plugin_active( $plugin_basename );
566
+ }
567
+ }
568
+ if ( empty( $addon->url ) ) {
569
+ $addon->url = '';
570
+ }
571
+
572
+ $active_version = false;
573
+ if ( $active ) {
574
+ if ( ! empty( $installed_plugins[ $plugin_basename ]['Version'] ) ) {
575
+ $active_version = $installed_plugins[ $plugin_basename ]['Version'];
576
+ }
577
+ }
578
+
579
+ $addon->type = $addons_type;
580
+ $addon->installed = $installed;
581
+ $addon->active_version = $active_version;
582
+ $addon->active = $active;
583
+ $addon->basename = $plugin_basename;
584
+
585
+ return $addon;
586
+ }
587
+
588
+ /**
589
+ * Use custom notices in the Vue app on the Settings screen.
590
+ */
591
+ public function hide_old_notices() {
592
+
593
+ global $wp_version;
594
+ if ( version_compare( $wp_version, '4.6', '<' ) ) {
595
+ // remove_all_actions triggers an infinite loop on older versions.
596
+ return;
597
+ }
598
+
599
+ $screen = get_current_screen();
600
+ // Bail if we're not on a ExactMetrics screen.
601
+ if ( empty( $screen->id ) || strpos( $screen->id, 'exactmetrics' ) === false ) {
602
+ return;
603
+ }
604
+
605
+ // Hide admin notices on the settings screen.
606
+ if ( exactmetrics_is_settings_page() ) {
607
+ remove_all_actions( 'admin_notices' );
608
+ }
609
+
610
+ }
611
+
612
+ /**
613
+ * Update manual ua.
614
+ */
615
+ public function update_manual_ua() {
616
+
617
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
618
+
619
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
620
+ return;
621
+ }
622
+
623
+ $manual_ua_code = isset( $_POST['manual_ua_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_ua_code'] ) ) : '';
624
+ $manual_ua_code = exactmetrics_is_valid_ua( $manual_ua_code ); // Also sanitizes the string.
625
+ if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
626
+ define( 'WP_NETWORK_ADMIN', true );
627
+ }
628
+ $manual_ua_code_old = is_network_admin() ? ExactMetrics()->auth->get_network_manual_ua() : ExactMetrics()->auth->get_manual_ua();
629
+
630
+ if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old === $manual_ua_code ) {
631
+ // Same code we had before
632
+ // Do nothing.
633
+ wp_send_json_success();
634
+ } else if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old !== $manual_ua_code ) {
635
+ // Different UA code.
636
+ if ( is_network_admin() ) {
637
+ ExactMetrics()->auth->set_network_manual_ua( $manual_ua_code );
638
+ } else {
639
+ ExactMetrics()->auth->set_manual_ua( $manual_ua_code );
640
+ }
641
+ } else if ( $manual_ua_code && empty( $manual_ua_code_old ) ) {
642
+ // Move to manual.
643
+ if ( is_network_admin() ) {
644
+ ExactMetrics()->auth->set_network_manual_ua( $manual_ua_code );
645
+ } else {
646
+ ExactMetrics()->auth->set_manual_ua( $manual_ua_code );
647
+ }
648
+ } else if ( empty( $manual_ua_code ) && $manual_ua_code_old ) {
649
+ // Deleted manual.
650
+ if ( is_network_admin() ) {
651
+ ExactMetrics()->auth->delete_network_manual_ua();
652
+ } else {
653
+ ExactMetrics()->auth->delete_manual_ua();
654
+ }
655
+ } else if ( isset( $_POST['manual_ua_code'] ) && empty( $manual_ua_code ) ) {
656
+ wp_send_json_error( array(
657
+ 'ua_error' => 1,
658
+ 'error' => __( 'Invalid UA code', 'google-analytics-dashboard-for-wp' ),
659
+ ) );
660
+ }
661
+
662
+ wp_send_json_success();
663
+ }
664
+
665
+ /**
666
+ * Update manual v4.
667
+ */
668
+ public function update_manual_v4() {
669
+
670
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
671
+
672
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
673
+ return;
674
+ }
675
+
676
+ $manual_v4_code = isset( $_POST['manual_v4_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_v4_code'] ) ) : '';
677
+ $manual_v4_code = exactmetrics_is_valid_v4_id( $manual_v4_code ); // Also sanitizes the string.
678
+
679
+ if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
680
+ define( 'WP_NETWORK_ADMIN', true );
681
+ }
682
+ $manual_v4_code_old = is_network_admin() ? ExactMetrics()->auth->get_network_manual_v4_id() : ExactMetrics()->auth->get_manual_v4_id();
683
+
684
+ if ( $manual_v4_code && $manual_v4_code_old && $manual_v4_code_old === $manual_v4_code ) {
685
+ // Same code we had before
686
+ // Do nothing.
687
+ wp_send_json_success();
688
+ } else if ( $manual_v4_code && $manual_v4_code_old && $manual_v4_code_old !== $manual_v4_code ) {
689
+ // Different UA code.
690
+ if ( is_network_admin() ) {
691
+ ExactMetrics()->auth->set_network_manual_v4_id( $manual_v4_code );
692
+ } else {
693
+ ExactMetrics()->auth->set_manual_v4_id( $manual_v4_code );
694
+ }
695
+ } else if ( $manual_v4_code && empty( $manual_v4_code_old ) ) {
696
+ // Move to manual.
697
+ if ( is_network_admin() ) {
698
+ ExactMetrics()->auth->set_network_manual_v4_id( $manual_v4_code );
699
+ } else {
700
+ ExactMetrics()->auth->set_manual_v4_id( $manual_v4_code );
701
+ }
702
+ } else if ( empty( $manual_v4_code ) && $manual_v4_code_old ) {
703
+ // Deleted manual.
704
+ if ( is_network_admin() ) {
705
+ ExactMetrics()->auth->delete_network_manual_v4_id();
706
+ } else {
707
+ ExactMetrics()->auth->delete_manual_v4_id();
708
+ }
709
+ } else if ( isset( $_POST['manual_v4_code'] ) && empty( $manual_v4_code ) ) {
710
+ wp_send_json_error( array(
711
+ 'v4_error' => 1,
712
+ 'error' => __( 'Invalid GAv4 code', 'google-analytics-dashboard-for-wp' ),
713
+ ) );
714
+ }
715
+
716
+ wp_send_json_success();
717
+ }
718
+
719
+ public function update_dual_tracking_id() {
720
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
721
+
722
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
723
+ return;
724
+ }
725
+
726
+ if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
727
+ define( 'WP_NETWORK_ADMIN', true );
728
+ }
729
+
730
+ $value = empty( $_REQUEST['value'] ) ? '' : sanitize_text_field( wp_unslash( $_REQUEST['value'] ) );
731
+ $sanitized_ua_value = exactmetrics_is_valid_ua( $value );
732
+ $sanitized_v4_value = exactmetrics_is_valid_v4_id( $value );
733
+
734
+ if ( $sanitized_v4_value ) {
735
+ $value = $sanitized_v4_value;
736
+ } elseif ( $sanitized_ua_value ) {
737
+ $value = $sanitized_ua_value;
738
+ } elseif ( ! empty( $value ) ) {
739
+ wp_send_json_error( array(
740
+ 'error' => __( 'Invalid dual tracking code', 'google-analytics-dashboard-for-wp' ),
741
+ ) );
742
+ }
743
+
744
+ $auth = ExactMetrics()->auth;
745
+
746
+ if ( is_network_admin() ) {
747
+ $auth->set_network_dual_tracking_id( $value );
748
+ } else {
749
+ $auth->set_dual_tracking_id( $value );
750
+ }
751
+
752
+ wp_send_json_success();
753
+ }
754
+
755
+ public function update_measurement_protocol_secret() {
756
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
757
+
758
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
759
+ return;
760
+ }
761
+
762
+ if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
763
+ define( 'WP_NETWORK_ADMIN', true );
764
+ }
765
+
766
+ $value = empty( $_REQUEST['value'] ) ? '' : sanitize_text_field( wp_unslash( $_REQUEST['value'] ) );
767
+
768
+ $auth = ExactMetrics()->auth;
769
+
770
+ if ( is_network_admin() ) {
771
+ $auth->set_network_measurement_protocol_secret( $value );
772
+ } else {
773
+ $auth->set_measurement_protocol_secret( $value );
774
+ }
775
+
776
+ // Send API request to Relay
777
+ // TODO: Remove when token automation API is ready
778
+ $api = new ExactMetrics_API_Request( 'auth/mp-token/', 'POST' );
779
+ $api->set_additional_data( array(
780
+ 'mp_token' => $value,
781
+ ) );
782
+
783
+ // Even if there's an error from Relay, we can still return a successful json
784
+ // payload because we can try again with Relay token push in the future
785
+ $data = array();
786
+ $result = $api->request();
787
+ if ( is_wp_error( $result ) ) {
788
+ // Just need to output the error in the response for debugging purpose
789
+ $data['error'] = array(
790
+ 'message' => $result->get_error_message(),
791
+ 'code' => $result->get_error_code(),
792
+ );
793
+ }
794
+
795
+ wp_send_json_success( $data );
796
+ }
797
+
798
+
799
+ /**
800
+ *
801
+ */
802
+ public function handle_settings_import() {
803
+
804
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
805
+
806
+ if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
807
+ return;
808
+ }
809
+
810
+ if ( ! isset( $_FILES['import_file'] ) ) {
811
+ return;
812
+ }
813
+
814
+ $extension = explode( '.', sanitize_text_field( wp_unslash( $_FILES['import_file']['name'] ) ) );
815
+ $extension = end( $extension );
816
+
817
+ if ( 'json' !== $extension ) {
818
+ wp_send_json_error( array(
819
+ 'message' => esc_html__( 'Please upload a valid .json file', 'google-analytics-dashboard-for-wp' ),
820
+ ) );
821
+ }
822
+
823
+ $import_file = sanitize_text_field( wp_unslash( $_FILES['import_file']['tmp_name'] ) );
824
+
825
+ $file = file_get_contents( $import_file );
826
+ if ( empty( $file ) ) {
827
+ wp_send_json_error( array(
828
+ 'message' => esc_html__( 'Please upload a file to import', 'google-analytics-dashboard-for-wp' ),
829
+ ) );
830
+ }
831
+
832
+ // Retrieve the settings from the file and convert the json object to an array.
833
+ $new_settings = json_decode( wp_json_encode( json_decode( $file ) ), true );
834
+ $settings = exactmetrics_get_options();
835
+ $exclude = array(
836
+ 'analytics_profile',
837
+ 'analytics_profile_code',
838
+ 'analytics_profile_name',
839
+ 'oauth_version',
840
+ 'cron_last_run',
841
+ 'exactmetrics_oauth_status',
842
+ );
843
+
844
+ foreach ( $exclude as $e ) {
845
+ if ( ! empty( $new_settings[ $e ] ) ) {
846
+ unset( $new_settings[ $e ] );
847
+ }
848
+ }
849
+
850
+ foreach ( $exclude as $e ) {
851
+ if ( ! empty( $settings[ $e ] ) ) {
852
+ $new_settings = $settings[ $e ];
853
+ }
854
+ }
855
+
856
+ global $exactmetrics_settings;
857
+ $exactmetrics_settings = $new_settings;
858
+
859
+ update_option( exactmetrics_get_option_name(), $new_settings );
860
+
861
+ wp_send_json_success( $new_settings );
862
+
863
+ }
864
+
865
+ /**
866
+ * Generic Ajax handler for grabbing report data in JSON.
867
+ */
868
+ public function get_report_data() {
869
+
870
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
871
+
872
+ if ( ! current_user_can( 'exactmetrics_view_dashboard' ) ) {
873
+ wp_send_json_error( array( 'message' => __( "You don't have permission to view ExactMetrics reports.", 'google-analytics-dashboard-for-wp' ) ) );
874
+ }
875
+
876
+ if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
877
+ define( 'WP_NETWORK_ADMIN', true );
878
+ }
879
+ $settings_page = admin_url( 'admin.php?page=exactmetrics_settings' );
880
+
881
+ // Only for Pro users, require a license key to be entered first so we can link to things.
882
+ if ( exactmetrics_is_pro_version() ) {
883
+ if ( ! ExactMetrics()->license->is_site_licensed() && ! ExactMetrics()->license->is_network_licensed() ) {
884
+ wp_send_json_error( array(
885
+ 'message' => __( "You can't view ExactMetrics reports because you are not licensed.", 'google-analytics-dashboard-for-wp' ),
886
+ 'footer' => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-dashboard-for-wp' ) . '</a>',
887
+ ) );
888
+ } else if ( ExactMetrics()->license->is_site_licensed() && ! ExactMetrics()->license->site_license_has_error() ) {
889
+ // Good to go: site licensed.
890
+ } else if ( ExactMetrics()->license->is_network_licensed() && ! ExactMetrics()->license->network_license_has_error() ) {
891
+ // Good to go: network licensed.
892
+ } else {
893
+ wp_send_json_error( array( 'message' => __( "You can't view ExactMetrics reports due to license key errors.", 'google-analytics-dashboard-for-wp' ) ) );
894
+ }
895
+ }
896
+
897
+ // We do not have a current auth.
898
+ $site_auth = ExactMetrics()->auth->get_viewname();
899
+ $ms_auth = is_multisite() && ExactMetrics()->auth->get_network_viewname();
900
+ if ( ! $site_auth && ! $ms_auth ) {
901
+ wp_send_json_error( array( 'message' => __( 'You must authenticate with ExactMetrics before you can view reports.', 'google-analytics-dashboard-for-wp' ) ) );
902
+ }
903
+
904
+ $report_name = isset( $_POST['report'] ) ? sanitize_text_field( wp_unslash( $_POST['report'] ) ) : '';
905
+
906
+ if ( empty( $report_name ) ) {
907
+ wp_send_json_error( array( 'message' => __( 'Unknown report. Try refreshing and retrying. Contact support if this issue persists.', 'google-analytics-dashboard-for-wp' ) ) );
908
+ }
909
+
910
+ $report = ExactMetrics()->reporting->get_report( $report_name );
911
+
912
+ $isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
913
+ $start = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : $report->default_start_date();
914
+ $end = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : $report->default_end_date();
915
+
916
+ $args = array(
917
+ 'start' => $start,
918
+ 'end' => $end,
919
+ );
920
+
921
+ if ( $isnetwork ) {
922
+ $args['network'] = true;
923
+ }
924
+
925
+ if ( exactmetrics_is_pro_version() && ! ExactMetrics()->license->license_can( $report->level ) ) {
926
+ $data = array(
927
+ 'success' => false,
928
+ 'error' => 'license_level',
929
+ );
930
+ } else {
931
+ $data = apply_filters( 'exactmetrics_vue_reports_data', $report->get_data( $args ), $report_name, $report );
932
+ }
933
+
934
+ if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
935
+ wp_send_json_success( $data['data'] );
936
+ } else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
937
+ // Use a custom handler for invalid_grant errors.
938
+ if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
939
+ wp_send_json_error(
940
+ array(
941
+ 'message' => 'invalid_grant',
942
+ 'footer' => '',
943
+ )
944
+ );
945
+ }
946
+
947
+ wp_send_json_error(
948
+ array(
949
+ 'message' => $data['error'],
950
+ 'footer' => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
951
+ )
952
+ );
953
+ }
954
+
955
+ wp_send_json_error( array( 'message' => __( 'We encountered an error when fetching the report data.', 'google-analytics-dashboard-for-wp' ) ) );
956
+
957
+ }
958
+
959
+ /**
960
+ * Install plugins which are not addons.
961
+ */
962
+ public function install_plugin() {
963
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
964
+
965
+ if ( ! exactmetrics_can_install_plugins() ) {
966
+ wp_send_json( array(
967
+ 'error' => esc_html__( 'You are not allowed to install plugins', 'google-analytics-dashboard-for-wp' ),
968
+ ) );
969
+ }
970
+
971
+ $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : false;
972
+
973
+ if ( ! $slug ) {
974
+ wp_send_json( array(
975
+ 'message' => esc_html__( 'Missing plugin name.', 'google-analytics-dashboard-for-wp' ),
976
+ ) );
977
+ }
978
+
979
+ include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
980
+
981
+ $api = plugins_api( 'plugin_information', array(
982
+ 'slug' => $slug,
983
+ 'fields' => array(
984
+ 'short_description' => false,
985
+ 'sections' => false,
986
+ 'requires' => false,
987
+ 'rating' => false,
988
+ 'ratings' => false,
989
+ 'downloaded' => false,
990
+ 'last_updated' => false,
991
+ 'added' => false,
992
+ 'tags' => false,
993
+ 'compatibility' => false,
994
+ 'homepage' => false,
995
+ 'donate_link' => false,
996
+ ),
997
+ ) );
998
+
999
+ if ( is_wp_error( $api ) ) {
1000
+ return $api->get_error_message();
1001
+ }
1002
+
1003
+ $download_url = $api->download_link;
1004
+
1005
+ $method = '';
1006
+ $url = add_query_arg(
1007
+ array(
1008
+ 'page' => 'exactmetrics-settings',
1009
+ ),
1010
+ admin_url( 'admin.php' )
1011
+ );
1012
+ $url = esc_url( $url );
1013
+
1014
+ ob_start();
1015
+ if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
1016
+ $form = ob_get_clean();
1017
+
1018
+ wp_send_json( array( 'form' => $form ) );
1019
+ }
1020
+
1021
+ // If we are not authenticated, make it happen now.
1022
+ if ( ! WP_Filesystem( $creds ) ) {
1023
+ ob_start();
1024
+ request_filesystem_credentials( $url, $method, true, false, null );
1025
+ $form = ob_get_clean();
1026
+
1027
+ wp_send_json( array( 'form' => $form ) );
1028
+
1029
+ }
1030
+
1031
+ // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
1032
+ exactmetrics_require_upgrader();
1033
+
1034
+ // Prevent language upgrade in ajax calls.
1035
+ remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1036
+ // Create the plugin upgrader with our custom skin.
1037
+ $installer = new ExactMetrics_Plugin_Upgrader( new ExactMetrics_Skin() );
1038
+ $installer->install( $download_url );
1039
+
1040
+ // Flush the cache and return the newly installed plugin basename.
1041
+ wp_cache_flush();
1042
+ wp_send_json_success();
1043
+
1044
+ wp_die();
1045
+ }
1046
+
1047
+ /**
1048
+ * Store that the first run notice has been dismissed so it doesn't show up again.
1049
+ */
1050
+ public function dismiss_first_time_notice() {
1051
+
1052
+ exactmetrics_update_option( 'exactmetrics_first_run_notice', true );
1053
+
1054
+ wp_send_json_success();
1055
+ }
1056
+
1057
+ /**
1058
+ * Get the notice status by id.
1059
+ */
1060
+ public function get_notice_status() {
1061
+
1062
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1063
+
1064
+ $notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
1065
+ if ( ! $notice_id ) {
1066
+ wp_send_json_error();
1067
+ }
1068
+ $is_dismissed = ExactMetrics()->notices->is_dismissed( $notice_id );
1069
+
1070
+ wp_send_json_success( array(
1071
+ 'dismissed' => $is_dismissed,
1072
+ ) );
1073
+ }
1074
+
1075
+ /**
1076
+ * Dismiss notices by id.
1077
+ */
1078
+ public function dismiss_notice() {
1079
+
1080
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1081
+
1082
+ $notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
1083
+ if ( ! $notice_id ) {
1084
+ wp_send_json_error();
1085
+ }
1086
+ ExactMetrics()->notices->dismiss( $notice_id );
1087
+
1088
+ wp_send_json_success();
1089
+ }
1090
+
1091
+ /**
1092
+ * Retrieve posts/pages
1093
+ *
1094
+ * @access admin
1095
+ * @since 3.0.0
1096
+ */
1097
+ public function get_posts() {
1098
+
1099
+ // Run a security check first.
1100
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1101
+
1102
+ $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( wp_unslash( $_POST['post_type'] ) ) : 'any';
1103
+
1104
+ $args = array(
1105
+ 's' => isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '',
1106
+ 'post_type' => $post_type,
1107
+ 'posts_per_page' => isset( $_POST['numberposts'] ) ? sanitize_text_field( wp_unslash( $_POST['numberposts'] ) ) : 10,
1108
+ 'orderby' => 'relevance',
1109
+ );
1110
+
1111
+ $array = array();
1112
+ $posts = get_posts( $args );
1113
+
1114
+ if ( in_array( $post_type, array( 'page', 'any' ), true ) ) {
1115
+ $homepage = get_option( 'page_on_front' );
1116
+ if ( ! $homepage ) {
1117
+ $array[] = array(
1118
+ 'id' => - 1,
1119
+ 'title' => __( 'Homepage', 'google-analytics-dashboard-for-wp' ),
1120
+ );
1121
+ }
1122
+ }
1123
+
1124
+ if ( $posts ) {
1125
+ foreach ( $posts as $post ) {
1126