[DigitalPoint] Better Google Analytics

[DigitalPoint] Better Google Analytics 1.0.10

No permission to download
Thanks for the update Shawn, I have one site where the real-time map is loading on the ACP main page and another site it doesn't, I didn't see a setting anywhere for this? or am I missing something?
 
As long as you setup the Google Analytics account link, it should work. Beyond that, the only time the map wouldn’t show (normally anyway) would be if there was no users to the site in the last 30 minutes (as in no real-time data to make a map from).
 
I'm receiving the following error:

Server error log
  • ParseError: syntax error, unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST)
  • src/addons/DigitalPoint/Analytics/GoogleApi/Measurement.php:17
  • Generated by: Unknown account
  • May 31, 2022 at 9:17 PM

Stack trace​

#0 src/vendor/composer/ClassLoader.php(346): Composer\Autoload\includeFile('/home/jdeadmin/...')
#1 [internal function]: Composer\Autoload\ClassLoader->loadClass('DigitalPoint\\An...')
#2 src/addons/DigitalPoint/Analytics/Repository/Measurement.php(21): spl_autoload_call('DigitalPoint\\An...')
#3 src/addons/DigitalPoint/Analytics/Repository/Measurement.php(11): DigitalPoint\Analytics\Repository\Measurement->getMeasurementApi()
#4 src/addons/DigitalPoint/Analytics/XF/Mail/Mailer.php(108): DigitalPoint\Analytics\Repository\Measurement->collect('dce22f9b-bf64-4...', Array, '23611')
#5 src/XF/Mail/Mail.php(458): DigitalPoint\Analytics\XF\Mail\Mailer->send(Object(Hampel\SparkPostDriver\Message), NULL, NULL, true)
#6 src/XF/Job/ActivitySummaryEmail.php(115): XF\Mail\Mail->send()
#7 src/XF/Job/ActivitySummaryEmail.php(68): XF\Job\ActivitySummaryEmail->generateAndSendEmail(Object(Snog\Flags\XF\Entity\User))
#8 src/XF/Job/Manager.php(260): XF\Job\ActivitySummaryEmail->run(8)
#9 src/XF/Job/Manager.php(202): XF\Job\Manager->runJobInternal(Array, 8)
#10 src/XF/Job/Manager.php(86): XF\Job\Manager->runJobEntry(Array, 8)
#11 job.php(43): XF\Job\Manager->runQueue(false, 8)
#12 {main}

Request state​

array(4) {
["url"] => string(18) "/community/job.php"
["referrer"] => string(43) "https://www.xxxcom/community/admin.php"
["_GET"] => array(0) {
}
["_POST"] => array(0) {
}
}

Delete
 
I'm receiving the following error:

Server error log
  • ParseError: syntax error, unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST)
  • src/addons/DigitalPoint/Analytics/GoogleApi/Measurement.php:17
  • Generated by: Unknown account
  • May 31, 2022 at 9:17 PM

Stack trace​

#0 src/vendor/composer/ClassLoader.php(346): Composer\Autoload\includeFile('/home/jdeadmin/...')
#1 [internal function]: Composer\Autoload\ClassLoader->loadClass('DigitalPoint\\An...')
#2 src/addons/DigitalPoint/Analytics/Repository/Measurement.php(21): spl_autoload_call('DigitalPoint\\An...')
#3 src/addons/DigitalPoint/Analytics/Repository/Measurement.php(11): DigitalPoint\Analytics\Repository\Measurement->getMeasurementApi()
#4 src/addons/DigitalPoint/Analytics/XF/Mail/Mailer.php(108): DigitalPoint\Analytics\Repository\Measurement->collect('dce22f9b-bf64-4...', Array, '23611')
#5 src/XF/Mail/Mail.php(458): DigitalPoint\Analytics\XF\Mail\Mailer->send(Object(Hampel\SparkPostDriver\Message), NULL, NULL, true)
#6 src/XF/Job/ActivitySummaryEmail.php(115): XF\Mail\Mail->send()
#7 src/XF/Job/ActivitySummaryEmail.php(68): XF\Job\ActivitySummaryEmail->generateAndSendEmail(Object(Snog\Flags\XF\Entity\User))
#8 src/XF/Job/Manager.php(260): XF\Job\ActivitySummaryEmail->run(8)
#9 src/XF/Job/Manager.php(202): XF\Job\Manager->runJobInternal(Array, 8)
#10 src/XF/Job/Manager.php(86): XF\Job\Manager->runJobEntry(Array, 8)
#11 job.php(43): XF\Job\Manager->runQueue(false, 8)
#12 {main}

Request state​

array(4) {
["url"] => string(18) "/community/job.php"
["referrer"] => string(43) "https://www.xxxcom/community/admin.php"
["_GET"] => array(0) {
}
["_POST"] => array(0) {
}
}

Delete
That should have been fixed a couple versions ago (fix for old versions of PHP). Can you double check you have the latest version?
 
Just one observation/question... When this add-on is enabled I see Universal Analytics gets completely disabled (no active stats showing or logging, if previously setup). Could you make an option to allow Universal Analytics to still process data until the admin is ready to fully switch over to using the GA4 property only.

It's just currently this add-on when enabled disables the default XenForo support for Universal Analytics. Not looking for this add-on to support UA, just looking for it to work along side XenForo's built in support for UA.

So basically if you are using UA Google Analytics with Google Tag Manager (which is how XF does it), even with custom events, you should be able to simply keep using those custom events with GA4 and/or dual tag without any changes to those events or code on your site since you can tell Google Analytics which of your UA sites you want to connect the data to for dual tagging on the backend with singular gtag() calls.

You are correct and that is what I currently have setup during my transition - UA is currently passing everything through to GA4. The issue is as soon as this add-on is enabled UA stops getting data. Which I assume is because this add-on somehow overrides/disables the existing Google Analytics UA property ID setting built into XenForo which is still required for the UA to GA4 pass-through to work.

Maybe I'm the only one who will care that this happens. Thanks again for the add-on.
One way round this seems to be to just add the old UA tag into PAGE_CONTAINER.

Code:
{{ $xf.runJobs ? ' data-run-jobs=""' : '' }}>
<head>
    <!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-10"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-xxxxxxxx-10');
</script>


    <meta charset="utf-8" />



Then both GA4 and UA stats will show in GA.
 
One way round this seems to be to just add the old UA tag into PAGE_CONTAINER.

Code:
{{ $xf.runJobs ? ' data-run-jobs=""' : '' }}>
<head>
    <!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-10"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-xxxxxxxx-10');
</script>


    <meta charset="utf-8" />



Then both GA4 and UA stats will show in GA.
There's no need to do this - if you setup a connected site tag in the GA4 property data stream then it will automatically send data to the old UA property.

1654082606179.webp

Connect it here and fill in the old UA ID.

If you have been doing something fancy with your analytics (for example I used dimensions) then you can simply edit the "ba_google_analytics" template and add the second config in there.

Mine for example looks like this (I add the user_id and dimension1)

Code:
<xf:if is="$xf.options.baCredentials.measurement_id">
    <xf:if is="$xf.options.baGeneral.host_gtm">
        <script async src="{{ link('javascript/gtm.js', '', {'_v': $xf.app.jsVersion}) }}"></script>
    <xf:else />
        <script async src="https://www.googletagmanager.com/gtag/js?id={$xf.options.baCredentials.measurement_id}"></script>
    </xf:if>
    <script>
        window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date);gtag('config','{$xf.options.baCredentials.measurement_id|escape("js")}',{<xf:trim>
</xf:trim><xf:trim>
            <xf:if is="$xf.cookie.domain">'cookie_domain': '{$xf.cookie.domain}',</xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.visitor.user_id && $xf.options.baItems.user_id">'user_id':'{$xf.visitor.user_id}',</xf:if>       
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baItems.style">'style_id':{$xf.style.style_id},</xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baItems.node && $forum.node_id">'node_id':{$forum.node_id},'node_title':'{$forum.Node.title|escape("js")}',</xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baItems.thread && $thread.thread_id">'thread_id':{$thread.thread_id},'thread_title':'{$thread.title|escape("js")}',</xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baItems.thread && $thread.prefix_id">'thread_prefix':'{{ prefix('thread', $thread)|escape("js") }}',</xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baItems.thread && $thread.username">'thread_author':'{$thread.username|escape("js")}',</xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baItems.thread_tag && $thread.tags">'thread_tag':'{$thread.tags|pluck("tag")|first|escape("js")}',</xf:if>
</xf:trim><xf:trim>
    <xf:if contentcheck="true">
        'user_properties': {
        <xf:contentcheck><xf:trim>
            <xf:if is="$xf.visitor.user_id && $xf.options.baItems.user_id">
                    'uid':{$xf.visitor.user_id},
            </xf:if>
        </xf:trim><xf:trim>
            <xf:set var="$userGroupSet" value="{{ false }}" />
            <xf:foreach loop="$xf.options.baUser.user_group" value="$userGroupId">
                <xf:if is="!$userGroupSet && $xf.visitor.isMemberOf($userGroupId)">
                    <xf:set var="$userGroupSet" value="{{ true }}" />
                    'user_group_id':{$userGroupId},
                </xf:if>
            </xf:foreach>
        </xf:trim></xf:contentcheck>
        },
    </xf:if>
</xf:trim><xf:trim>
            <xf:if is="$xf.options.baDebug">'debug_mode':true,</xf:if>
        </xf:trim>});
        
        // ORIGINAL UA ANALYTICS WITH CUSTOM DIMENSIONS   
        gtag('config', '{$xf.options.googleAnalyticsWebPropertyId|escape("js")}', {
            // <!--[XF:ga:config_start]-->
            <xf:if is="$xf.cookie.domain">
                'cookie_domain': '{$xf.cookie.domain}',
            </xf:if>
            <xf:if is="$xf.options.googleAnalyticsAnonymize">
                'anonymize_ip': true,
            </xf:if>
            <xf:if is="$xf.visitor.user_id">
                'user_id': '{$xf.visitor.user_id}',
            </xf:if>
                'dimension1': '<xf:if is="$xf.visitor.user_id">Registered<xf:else />Unregistered</xf:if>',
        });           
        // ORIGINAL UA ANALYTICS WITH CUSTOM DIMENSIONS   

<xf:if is="$xf.options.baItems.errors">!function(b,c){"object"==typeof console&&"function"==typeof console.error&&(console.error_old=console.error,console.error=function(){console.error_old.apply(this,arguments);b.gtag("event","exception",{error_type:"console",error_message:arguments[0],fatal:!1})});b.onerror=function(a,d,e){b.gtag("event","exception",{error_type:"javascript",error_message:a,error_location:d,error_line_number:e,fatal:!1})};b.onload=function(){c.querySelectorAll("img").forEach(a=>{a.complete&&0===a.naturalWidth&&b.gtag("event",
"exception",{error_type:"image",error_message:"not_loaded",error_location:a.src,fatal:!1})})}}(window,document);</xf:if>
    </script>
</xf:if>
 
There's no need to do this - if you setup a connected site tag in the GA4 property data stream then it will automatically send data to the old UA property.
I'm sure that's true, I just find my brain starts to hurt when I go to Google Analytics and try to do stuff and I found it easier to just paste the tag in the template.
 
I'm sure that's true, I just find my brain starts to hurt when I go to Google Analytics and try to do stuff and I found it easier to just paste the tag in the template.
Ok but your method will now load the Analytics JS script twice - once locally and now once remotely.....
 
There's no need to do this - if you setup a connected site tag in the GA4 property data stream then it will automatically send data to the old UA property.

View attachment 269034

Connect it here and fill in the old UA ID.

This was not my experience. I setup my old UA account in that setting and no live data showed on UA.

It appears the only way to get both GA4 and UA processing data, with this add-on enabled, is to modify a template (like PAGE_CONTAINER) and duplicate Google Analytics code for the entire site.
 
This was not my experience. I setup my old UA account in that setting and no live data showed on UA.

It appears the only way to get both GA4 and UA processing data, with this add-on enabled, is to modify a template (like PAGE_CONTAINER) and duplicate Google Analytics code for the entire site.
I'm testing this as we speak. Will probably need until sorrow to know whether or not it's working for me
 
@Stylesfactory Could you possibly look at compatibility issues with this addon please? My node icons look strange.

I posted earlier in the thread with how it looks. You can also see on my site.
 
so... i am not an expert in deciphering analytics data. i mostly stick to realtime stats and user visits on a daily basis.
when i click the graph icon at the top right. i land on a graph that does show user visits for that page.
but it is divided into browser based groups. was wondering if it's possible to add another value for total visits? cheers.
 
so... i am not an expert in deciphering analytics data. i mostly stick to realtime stats and user visits on a daily basis.
when i click the graph icon at the top right. i land on a graph that does show user visits for that page.
but it is divided into browser based groups. was wondering if it's possible to add another value for total visits? cheers.
Made some changes internally to facilitate the ability to not choose a dimension (which is the thing that breaks it down by something like browser). So ya... now there's a "Totals" section in the Dimension selector drop-down:

1654110457045.webp

...which internally is choosing no dimension, but a variable metric. That way you can choose what exactly you want the totals to be (maybe someone wants to see page views, while someone else wants to see sessions). As a bonus, if you have linked your Google Analytics property to your Google Search Console, you have the ability to chart some metrics that ultimately come from Google Search Console (like the Organic Google search items).

For example, this is Google search impressions (how many times my site showed up in Google search results) for a new site I have (it looks like the data is delayed by a day or two in Google Search Console, but you get the idea):

1654110678527.webp

It's all working on my end, so will be part of the next update.
 
Just curious... Anyone else getting:

Code:
Uncaught TypeError: Cannot read properties of undefined (reading 'prototype')

In Client-side errors panel? I assume this could be related to addons I have.
 
Top Bottom