Send event parameters with every event and multiple tags in Google Analytics 4


There are some event parameters that are useful to send with every event. Google has a helpful guide here which even covers the case where you have multiple tags (I'm running GA4 and UA during the migration and this isn't unusual). You're supposed to call gtag set before calling config on each tag. This isn't working for me though, I see nothing coming through in the debug view.

Calling set before config works fine for user properties (my journey of discovery yesterday) but unless I was doing something stupid that I haven't seen yet no dice for event parameters. The code above uses the config method of initialization with a shared object to prevent duplicating code. This seems to work fine.

(Related: Export Google Fit Daily Steps, Weight and Distance to a Google Sheet; User scoped custom dimensions in Google Analytics 4 using gtag; Using the Azure Monitor REST API from Google Apps Script)

(You might also like: Top 5 reasons to hate the Facebook like button; Go-arounds: LEGO and Legislative Service; Stars over Casini Ranch, a Timelapse)

(All Code Posts)

User scoped custom dimensions in Google Analytics 4 using gtag

A user parameter in the GA4 debug view

Given that everything in Google Analytics 4 is an event I expected user scoped custom dimensions to be a regular event parameter as well. They're not. And most of the documentation both from Google and others talks about Google Tag Manager which doesn't help if you're just using gtag. It's not that hard to implement, but figuring out all the pieces was way harder than it should be. I hope this helps the next person...

To create a user scoped custom dimension you need a user property. This is different from an event property. In gtag you need to call set on user_properties with an object containing the user properties to set like this:

If you want the user property on the hit sent with page load do this right before the config call when loading your gtag (you can do it as part of the config call if you're just setting up one tag, or as above before the config call which is helpful if using more than one tag). If you don't know the value of the user property at page load time you can also set it and then send an event.

From the client you can inspect the beacon sent to GA4 for an event, for example:

Event parameters get a prefix of ep or epn. In this case I'm using a parameter rc_score set to 0.9 which appears in the beacon as epn.rc_score=0.9. GA auto-detects numeric values and uses epn for these. The user parameter gets a up prefix and in this case is up.user_quality=low. (In this specific case I'm sending a recapture score as both a custom metric and a user scoped dimension so I can segment out high and low quality users, at least from the perspective of recapture).

More visually you can use the debug view in the configure section of GA4 (why there are settings in the reporting interface as well as the settings interface I have no idea). To use this pass { 'debug_mode':true } to your gtag config call. To confirm that you're getting user properties look for an orange icon in the timeline (see screenshot at the top of this post). There is also a helpful user properties active now box at the bottom right of this screen.

Once you have this working you still need to wire it up in GA4. Wait 24 hours... then go to Configure -> Custom definitions. Add a new custom dimension, make sure you pick user scoped and you should then be able to select the user property to use to populate the dimension.

(Related: Using the Azure Monitor REST API from Google Apps Script; Automate Google PageSpeed Insights and Core Web Vitals Logging with Apps Script; Export Google Fit Daily Steps, Weight and Distance to a Google Sheet)

(You might also like: San Francisco New Year's Eve Timelapse; Northern Pacific Rattlesnake; About Hikes)

(All Code Posts)

Fortune Cookies for Android 1.30

Fortune Cookies for Android 1.30

I've just released Fortune Cookies for Android 1.30. The last update was in... 2013... it turns out the Android ecosystem has moved on a bit since then and it wasn't even in the Play Store any more as a result. This update has a nice modern theme but is otherwise just an Android version of the classic UNIX fortune command. The database of fortunes is ancient and just running this might get you canceled / fired / etc so use with due caution. If you have this installed it will update as soon as the release is approved.

(Related: Going Chrome; Catfood Software Support; The Secret Diary of a Xamarin Android Developer, Aged 48 1/3)

(You might also like: Route map and elevation profile for Hike Posts; Summer Solstice 2019; Dog First Aid)

(All Code Posts)

Catfood Earth 4.30

Updated on Sunday, October 23, 2022

Catfood Earth Satellite Composite Image of Earth including Volcanoes and Earthquakes

Catfood Earth 4.30 is available to download.

This update fixes a couple of problems with the screensaver. It now has improved support for multiple monitors (the image will repeat rather than stretch). There was a problem with the screensaver not starting in some cases. This should now be fixed. After upgrading to 4.30 please find and run the 'Catfood Earth Screensaver Settings' shortcut to configure the screensaver.

4.30 also includes version 2022d of the time zone database.

(Related: Catfood Earth; Improving the accuracy of the new Catfood Earth clouds layer; Catfood Software Support)

(You might also like: One Year of Tides Animated (with Sun and Moon); A black lab chases a Roomba and then things start to get weird...; National Popular Vote)

(All Code Posts)

Autumnal Equinox 2022

Catfood Earth render of the exact moment of the Autumnal (Fall) Equinox 2022.

Autumn (or Fall) starts now (23 September 2022, 01:04 UTC) in the Northern Hemisphere, Spring if you happen to be south of the Equator. Rendered in Catfood Earth.

(Related: Autumnal Equinox 2021; Autumnal Equinox 2014; Autumnal Equinox 2015)

(You might also like: West Portal Sunset; Harbor Seals; Photo Sorter)

(All Code Posts)

Photo Sorter 1.20

Updated on Sunday, October 2, 2022

Photo Sorter 1.20

Photo Sorter has been updated to handle some duplicates I've been developing in Google Photos. These are pretty specific rules but might be helpful if you are trying to maintain a local archive from Google Photos via Google Takeout. You can get the latest binary and source from github (or fork away if it's not quite what you need).

The first change is that Photo Sorter now checks for duplicates in the source folder as well as the destination. If two source files have the same date taken and the same filename then the larger file is chosen as the winner and the smaller file is deleted. The filename check ignores anything in parentheses, so 123.jpg is considered to be the same filename as 123(1).jpg. This helps alleviate a fun bug where Google Photos will export via the API a different file that was originally uploaded. I've stopped using the Google Photos API for this reason, and because it will under no circumstances allow you to download a video that is the same quality as the original upload. Crazy edge case Google. Happily Google Takeout still works so I'm stuck doing it slowly and wastefully.

The second change is that if a source duplicate is found using the rules above then it will also be deleted from the destination folder (in order to be replaced by the presumed better version of itself).

Photo Sorter copies some folder full of photos and movies to a different folder with a clean structure and some de-duplication. It's been keeping me sane since 2018.

(Related: Photo Sorter; How to backup Google Photos to Google Drive automatically after July 2019 with Apps Script; Capture DropCam (Nest Cam) frames to Google Drive)

(You might also like: Pelicans; Treasure Island Perimeter; Enable GZIP compression for Amazon S3 hosted website in CloudFront)

(All Code Posts)

Catfood WebCamSaver 3.29.0002

Updated on Saturday, September 24, 2022

Catfood WebCamSaver 3.29.0002

Catfood WebCamSaver 3.29 is now available to download.

This release updates the webcam list and includes a selection of new webcams provided by a long-time user.

(Related: Catfood WebCamSaver; Catfood: WebCamSaver and PdfScan; ESRI Shapefile Reader in .NET)

(You might also like: San Francisco New Year's Eve Timelapse 2020; AT&T MicroCell Woes; Winter Solstice 2019)

(All Code Posts)

Summer Solstice 2022

Summer Solstice 2022

Summer starts right now (09:14 UTC June 21 2022) in the northern hemisphere, winter for those with latitude signum differences. Rendered in Catfood Earth.

(Related: Summer Solstice 2021; Summer Solstice 2017; Winter Solstice 2020)

(You might also like: You won't believe this one crazy trick that would fix the broken patent system; Autumnal Equinox 2017; Digital Services Act)

(All Code Posts)

Outlook/Office iCal feed 400 bad request error with C# WebClient

Updated on Tuesday, June 21, 2022


Just in case it helps someone else I was able to fetch an Outlook iCal feed using C#'s WebClient for years until it stopped working in June, 2022 with a 400 / bad request error. I was downloading a set of calendars and the fix was just to use a new WebClient for each calendar so it must be some kind of state thing in WebClient.

To regain around 1% of sanity I have a task that pulls the various calendars that life throws at me and combines them into a single, de-duplicated calendar. The Google Calendar on my phone is gorgeous as a result. My primary calendar is orange and then all of the miscellanea are teal and unique. It would be great if Google Calendar could do this without help, but it was worth the effort not to have some random soccer match repeated five times in different colors.

Last week one calendar, an Outlook feed, started failing with 400 bad request.

Naturally I assumed that the server had started to suddenly care about some header or other and I started playing around with setting User-Agent and various Accept headers without any luck. To make debugging slightly easier I moved the Outlook calendar out of a loop (where I was iterating through a list of iCal feeds that I need to be aware of) and then it magically started working. The magic in this case must be a fresh WebClient and so the fix was to use a new WebClient for each calendar instead of reusing a single instance. It looks like WebClient is deprecated in .NET 6 and one is supposed to start using HttpClient instead so that's probably another fix but not one I'm going to wrestle with today.

(Related: The Secret Diary of a Xamarin Android Developer, Aged 48 1/3; 1,000th Post!; Export Google Fit Daily Steps, Weight and Distance to a Google Sheet)

(You might also like: Did anyone tell Material Design about Gesture Navigation?; California, I can save you billions with a small and reasonably priced computer program...; Autumnal Equinox 2022)

(All Code Posts)

Catfood WebCamSaver 3.28

Updated on Friday, June 24, 2022

Catfood WebCamSaver 3.28

Catfood WebCamSaver 3.28 is available to download.

This release updates the webcam list.

(Related: Catfood WebCamSaver; Fortune Cookies for Android; Catfood: WebCamSaver and PdfScan)

(You might also like: How to get technical support without spending hours on the phone; Robot Ahead; Western Garter Snake)

(All Code Posts)