[DigitalPoint] Better Google Analytics

[DigitalPoint] Better Google Analytics 1.1.3

No permission to download
How does the "Host Google Tag Manager JavaScript on your own domain" work? I think this tries to load /jc/gtm.js ? Is that dynamically generated? I don't the addon is able to create it for me, as there's no such file
 
Heh, I didn't remember that I had created special rule for serving *.js files, had to create exempt for that. Once again, can only blame myself 😅
 
Heh, I didn't remember that I had created special rule for serving *.js files, had to create exempt for that. Once again, can only blame myself 😅
Probably better to apply special rules that route a request away from the application (XenForo) only if the file exists in the filesystem. I mean if you want to do it “right”. 😀

XenForo can handle any extension, so not sending certain requests to XenForo based on extension isn’t the best, so a check on that logic if the file exists or not would be better (I know, just repeating).
 
  • GuzzleHttp\Exception\ServerException: XF\Job\MailSend: Server error: POST https://www.google-analytics.com/mp/collect?measurement_id=G-xxx&api_secret=xxx resulted in a 502 Bad Gateway response:<!DOCTYPE html><html lang=en> <meta charset=utf-8> <meta name=viewport content="initial-scale=1, minimum-scale=1, w (truncated...)
  • src/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113
  • Generated by: Unknown account
  • May 3, 2026 at 12:59 AM

Stack trace​


#0 src/vendor/guzzlehttp/guzzle/src/Middleware.php(72): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response), NULL, Array, NULL)
#1 src/vendor/guzzlehttp/promises/src/Promise.php(209): GuzzleHttp\Middleware::GuzzleHttp\{closure}(Object(GuzzleHttp\Psr7\Response))
#2 src/vendor/guzzlehttp/promises/src/Promise.php(158): GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), NULL)
#3 src/vendor/guzzlehttp/promises/src/TaskQueue.php(52): GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}()
#4 src/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(163): GuzzleHttp\Promise\TaskQueue->run()
#5 src/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(189): GuzzleHttp\Handler\CurlMultiHandler->tick()
#6 src/vendor/guzzlehttp/promises/src/Promise.php(251): GuzzleHttp\Handler\CurlMultiHandler->execute(true)
#7 src/vendor/guzzlehttp/promises/src/Promise.php(227): GuzzleHttp\Promise\Promise->invokeWaitFn()
#8 src/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\Promise\Promise->waitIfPending()
#9 src/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\Promise\Promise->invokeWaitList()
#10 src/vendor/guzzlehttp/promises/src/Promise.php(69): GuzzleHttp\Promise\Promise->waitIfPending()
#11 src/addons/DigitalPoint/Analytics/GoogleApi/Measurement.php(22): GuzzleHttp\Promise\Promise->wait()
#12 src/addons/DigitalPoint/Analytics/Repository/Measurement.php(11): DigitalPoint\Analytics\GoogleApi\Measurement->__destruct()
#13 src/addons/DigitalPoint/Analytics/XF/Mail/Mailer.php(99): DigitalPoint\Analytics\Repository\Measurement->collect('fb3059b7-e06e-4...', Array, '325457')
#14 src/XF/Job/MailSend.php(37): DigitalPoint\Analytics\XF\Mail\Mailer->send(Object(Symfony\Component\Mime\Email))
#15 src/addons/DBTech/Mail/XF/Job/MailSend.php(26): XF\Job\MailSend->run(22.4301)
#16 src/XF/Job/Manager.php(275): DBTech\Mail\XF\Job\MailSend->run(22.4301)
#17 src/XF/Job/Manager.php(205): XF\Job\Manager->runJobInternal(Array, 22.4301)
#18 src/XF/Job/Manager.php(89): XF\Job\Manager->runJobEntry(Array, 22.4301)
#19 src/XF/Cli/Command/RunJobs.php(58): XF\Job\Manager->runQueue(false, 45)
#20 src/vendor/symfony/console/Command/Command.php(298): XF\Cli\Command\RunJobs->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 src/vendor/symfony/console/Application.php(1040): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 src/vendor/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand(Object(XF\Cli\Command\RunJobs), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 src/vendor/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 src/XF/Cli/Runner.php(115): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#25 cmd.php(17): XF\Cli\Runner->run()
#26 {main}


Request state​

array(1) {
["cli"] => string(62) "/cmd.php xf:run-jobs"
}

php 8.3.30
xf2.3.10
I recently moved to a new server.
 
Not sure if its relevant or accurate, but I ran it through Claude Code and got this response:

The ServerException propagates up uncaught, terminating the MailSend job. Queued emails are not sent until the job is retried and the GA endpoint happens to be healthy.

Root Cause​

The issue originates in Measurement.php line 22, called from the __destruct() method of DigitalPoint\Analytics\GoogleApi\Measurement. The Guzzle promise is resolved with ->wait() without any error handling. The call chain is:

Mailer->send() calls Repository\Measurement->collect()

collect() triggers GoogleApi\Measurement->__destruct()

__destruct() calls Promise->wait() on the pending GA request

If the GA endpoint returned a 5xx, wait() throws GuzzleHttp\Exception\ServerException

No try/catch exists at any level in this chain

Suggested Fix​

Wrap the Promise->wait() call in Measurement.php (or the __destruct method) in a try/catch that catches GuzzleHttp\Exception\GuzzleException (or at minimum ServerException). Log the failure via \XF::logException() and return gracefully. For example:



public function __destruct()

{

try {

$this->promise->wait();

} catch (\GuzzleHttp\Exception\GuzzleException $e) {

\XF::logException($e, false, 'DigitalPoint Analytics: GA4 measurement failed: ');

}

}
 
It’s a server-side error on Google’s side (or a proxy if your server is going through a proxy). 5xx errors are on the side of the server receiving the request and can’t be fixed on your side. You can disable serving the JavaScript from your own domain to work around it (no request to Google’s servers to fetch the JavaScript in that case).
 
Back
Top Bottom