Release Notes

Below is a complete list of changes for each release of utag.js.

Update your copy of utag.js to take advantage of the latest fixes and enhancements.

4.49 (September 2022)

4.45 - 4.48

4.48 (April 2021)

  • utag.js version 4.48 template updated with secure_cookie setting.

4.47 (January 2021)

  • Adds defensive code for potential jQuery vulnerability. Checks to make sure the src of a JavaScript file is set directly and not inherited from a compromised Object.prototype. This issue was fixed in jQuery 3.5.0, but re-introduced in 3.5.1.

  • Update to check for Array type with the built-in utag.ut.typeOf function instead of using instance of. Fixes issue with utag.js running in iframe in a testing environment (such as Cypress) and JavaScript instance of operation not working correctly.

4.46 (June 2018)

  • Adds support for the following new built-in variables:
    • tealium_session_number - a duplicate of the existing value in utag.data['cp.utag_main__sn']
    • tealium_session_event_number - the cookie value in utag.data['cp.utag_main__se'] that counts the number of tracking calls (utag.view(), utag.link()) in the current session (visit). This is useful for Single Page Apps (SPAs) where there is only one page load with many tracked events on that page. For pages using the noview flag, the value is ‘1’ for both page load (load rule evaluation) and the first call to utag.view().
  • Adds support for an empty param list passed into utag.link, utag.view or utag.track calls. In previous versions, calls to utag.link() or utag.view() work fine, but gets an extra “cfg” object added to the data layer. Calls to utag.track() causes an exception in previous versions.
  • For pages using noview flag, there are two things to keep in mind:
    • The data layer will have a ‘1’ value for tealium_session_event_number for both page load (utag.js uses data layer to loads in tags) and first call to utag.view (which fires tags and/or loads in more tags.)
    • Because cookies are used and initialized at page load time, if the utag.view call does not happen in time on the first page, and the page is refreshed in browser, it moves to ‘2’ for the first utag.view call which happens on second page. This is an edge case since most implementations calls utag.view immediately after utag.js executes.
  • This update also includes fixes for the “OU” function used by legacy Privacy Manager Extension.
    • The OPTOUTMULTI cookie is re-checked with each call to utag.view/link (no page refresh required)
    • Tags fired directly by tag’s UID also checks the OPTOUTMULTI cookie settings before firing

4.45 (January 2018)

  • Fixes bug introduced in version 4.40 that added an extra entry in browser history for pages that loaded the same tag in an iframe more than once. This issue likely impacted Single Page Apps (SPAs) using iframe-based tag vendors.

4.43 - 4.44

4.44 (June 2017)

  • Added support for visitor session counting for utag.js hosted on “tags.tiqcdn.cn” (China).
  • Updated the default utag_main cookie domain logic for domains following the pattern “example.XX.jp” (where cookies cannot be set in the XX.jp domain, but are set in “example.XX.jp” domain).

4.43 (June 2017)

  • Removed use of global variable i – previously used in loop through global variable utag_cfg_ovrd (config override object)
  • Removed legacy s2s support (as this was previously removed from Tealium iQ.) Cloud Delivery supported in Tealium Customer Data Hub.
  • Adds support for error handler function passed into utag.ut.loader utility function. This is only for modern browsers (older browser may the standard callback “cb” function instead)
utag.ut.loader({
        "src"   : "https://www.example.com/path/file.js",
        "cb"    : function(){console.log("CALLBACK")},
        "error" : function(){console.log("ERROR IN LOADING")}
        });

4.40 - 4.42

4.42 (August 2016)

Add new built-in Tealium event attributes. These new attributes are added to the data layer with each Tealium view or link event.

  • tealium_visitor_id The Tealium-generated ID in the cookie cp.utag_main_v_id
  • tealium_session_id The epoch timestamp string of current session start in ms
  • tealium_account The account string value in the path to the utag.js file
  • tealium_profile The profile string value in the path to the utag.js file
  • tealium_environment The environment string value in the path to the utag.js file. For example, “dev” or “prod”.
  • tealium_datasource The data source key from Tealium EventStream.
  • tealium_random A random number as a string for use in cache busting
  • tealium_library_name The name of the library (utag.js)
  • tealium_library_version The version of the utag.js. For example, “4.42.0” for this release)
  • tealium_timestamp_epoch Current epoch time in seconds as an integer
  • tealium_timestamp_utc Current ISO string timestamp for UTC time zone (not available on older browsers)
  • tealium_timestamp_local Current ISO string timestamp for browser’s time zone (not available on older browsers)

4.41

Minor update to fix typo for the fallback function in utag.ut.encode.

The encodeURIComponent call now falls back to use JavaScript’s escape call for the exception when encoding badly formed unicode characters.

4.40 (April 2016)

Improvements in behavior in Single Page App (SPA) sites using utag.link and utag.view

Previously, items in current data layer passed to utag.link/view were merged into the utag.data global object. This was required to re-evaluate load rules for each utag.link/view call. The utag.js 4.40 template takes advantage of a publish engine update so that this is no longer required. In version 4.40, the utag.data global object is not updated with each utag.link or utag.view call.

You may use the following JS Extension to test for backwards compatibility with 4.39 behavior before updating to 4.40.

// JS Extension scoped to "Before Load Rules"
utag.ut.merge( b, utag.data, 0 );
utag.ut.merge( utag.data, b ,1 );

New “noconsole” flag.

Setting the flag in utag_cfg_ovrd object to true stops any output from utag.DB from displaying in the web console. If debugging is enabled, the output still persist in the utag.db_log array.

Creating an iframe in DOM using utag.ut.loader function

If an iframe with the same ID already exists, the iframe is not added again. Instead, the iframe src is updated.

Updating JS Page vars value for utag.view or utag.link calls

JS Page vars are now updated to their current value with every call to utag.view or utag.link. As a result the b["js_page.my_global_var"] has the latest value in window.my_global_var each time utag.link is called.

Bug fix to keep cp.utag_main_ses_id in the data layer with every utag.link or utag.view call

The value is now updated with a new session ID following a utag.link/view call that occurs when the visitor has been on the same page for 30 minutes with no activity.

Removed trick to use eval to read the document.referrer value into the data layer’s b["dom.referrer"]

New utag.ut.encode function

This function falls back to use escape when encodeURIComponent issues an exception (an exception is possible when attempting to encode Unicode characters that are incomplete or incorrectly formed).

_t_visitor_id and _t_session_id are no longer available

Auto-generated data layer values _t_visitor_id and _t_session_id are no longer available. These are replaced by ut.visitor_id and ut.session_id. If still desired, add them back in as follows:

// JS Extension scoped to "Before Load Rules"
b["_t_visitor_id"] = b["cp.utag_main_v_id"];
b["_t_session_id"] = b["cp.utag_main_ses_id"];

4.36 - 4.39

4.39 (July 2015)

  • Adds support for the Tealium Collect Tag that writes visitor enrichment data to a profile-specific location in local storage.

4.38 (June 2015)

  • Supports a new drop-down list for selecting when to execute an All-Tags-scoped Extension.
    • After Load Rules (default selection)
    • Before Load Rules (not supported by 4.37 and below)
    • After Tags (not supported by 4.37 and below)

This feature is not compatible with 4.37 below as they may cause the Extension to run more than once.

  • Added support for calling utag.view before all the Tags have loaded; this fixes a bug when calling utag.view to fire a specific Tag by its UID inside a DOM Ready-scoped Extension.
  • Added support for calling utag.link for a specific Tag by its UID.

4.37 (February 2015)

  • Fixed a bug that incorrectly decodes any instance of $ value in the utag_main cookie and render it as a separator instead. Following this fix, the utag_main cookie values are not ‘double decoded’ anymore.
  • Fixed a bug that caused the utag_main__ss cookie to be set incorrectly when the readywait flag was set and /or the utag_data object was absent from the page.

4.36 (January 2015)

  • Load new tags on call to utag.link(). Calling utag.link() can load tags not already on the page.
  • Fixed a bug in which the utag.data object was not initialized for DOM Ready-scoped extensions when the waittimer and readywait flags were set to true.
  • Added new built-in Data Layer variables:
    • utag.data["ut.domain"]: The website’s domain
    • utag.data["ut.version"]: The version of utag.js loading on the site
    • utag.data["ut.event"]: The type of event (link or view)
    • utag.data["ut.account"]: The Tealium iQ account on the site
    • utag.data["ut.profile"]: The Tealium iQ profile on the site
    • utag.data["ut.env"]: The publish environment
  • Fixed a bug in which manual utag.view and utag.link calls were not extending the session end cookie timestamp. This is especially useful for single-page apps and sites that rely on AJAX to keep the session open while the visitor interacts with the site.
  • Fixed a bug for blocking Tags that prevented synchronously loading Tags from being used as blocking Tags.
  • Fixed a bug that prevented the loading of multiple synchronous blocking Tags from cache for older of Internet Explorer.
  • Added debugging to output the Data Layer at the point right before All Tags-scoped extensions run.

4.26 - 4.35

4.35 (December 2014)

  • Fixed a bug in which the Data Layer was not preserved for utag.view() calls made in rapid succession. Now a snapshot of the Data Layer is preserved for each call.
  • Added more debugging output for manual utag.view() and utag.link() calls.
  • Added a new utility function: utag.ut.typeOf(). For example, utag.ut.typeOf([]) returns the value “array”.

4.34 (October 2014)

  • Added an override (utag_cfg_ovrd) flag to utag.js in order to delay the loading of Tags until the DOM readyState “complete” (AKA “load”) event. This flag provides a delay that may improve page display time speeds by causing all Tags with the Wait = Yes setting to execute even later. Set this flag by entering the following code into a PreLoader-scoped JavaScript Code extension:
    var utag_cfg_ovrd = {};
    utag_cfg_ovrd.dom_complete = true;
  • Fixed a bug for the Internet Explorer browser in which the DOM readyState was reported as “interactive” prematurely. An extra delay for readyState “complete” was added for older of Internet Explorer.

4.33 (September 2014)

  • Added two new DOM Variables (formerly Data Sources): browser height (dom.viewport_height) and browser width (dom.viewport_width). Use these in Load Rules to detect when a visitor is using a certain devices to browse your site. For example, when this value is less than 480, you might assume the visitor is using a phone device. Try this on your phone for fun.
  • Added support for custom attributes on iframes/scripts to the utag.ut.loader function.
  • Fixed a bug in which Tags were not loading in order indicated in the Tags tab when fired by a manual utag.view call.

4.32 (August 2014)

  • Fixed a bug with Publish Settings so that you may now enable both the Ready Wait Flag and Bundling Libs publish settings for the same profile.
  • Fixed a bug in which enabling the Ready Wait Flag setting caused the utag.cfg.noview flag to reset to “false” if you had set it to “true”.
  • Introducing the new configuration flag, Wait Timer (utag_cfg_ovrd.waittimer). Tags do not load until the DOM Ready signal goes out. With this flag set exactly how long after the DOM Ready signal the Tags wait before they load. Setting this flag exposes the load time of a webpage without including the load times of 3rd-party vendor Tags. You set this value in milliseconds.

Here is an example of how to set the Wait Timer flag:

    var utag_cfg_ovrd={};
    utag_cfg_ovrd.waittimer=3000;

This code snippet delays the loading of all Tags until 3 seconds after the DOM Ready signal.

4.31 (May 2014)

  • Fixed a UTAG utility function bug for IE browsers when bringing in external JavaScript files and running a callback function. This addresses a rare timing issue in which the callback function runs too soon.

  • Introduces additional debugging output for when utag.view is called before all Tags are loaded. The Tag UID which may have an error now shows up in the output.

4.30 (April 2014)

  • Fixes a bug with the IE browser (9 and earlier) in which manual utag.view calls do not fire if your last Tag set to Wait = Yes did not fire and utag.X.js files were cached.
  • The utag.js now uses the values in the OPTOUTMULTI (Privacy Manager Extension) cookie for every utag.view call. Tags that are opted-out no longer fire for utag.view calls fired with AJAX content.

4.29 (April 2014)

  • Fixes a bug which prevented support for more than one blocking Tag. You may now have more than one Tag act as a blocking Tag. For example, Tealium Currency Converter with another external .js file.
  • Extensions scoped to “All Tags” run after any blocking Tags complete.
  • The utag.v.js file is no longer sent in the situation that you are self-hosting the utag.js file.
  • Removed “top.” from visitor ID generation logic. This fixes issues with iframes.

4.28 (February 2014)

  • Fixes an issue in which the page number (_pn) and session number (_sn) values are set to NaN whenever a visitor visits a website in which the utag_main session cookies was already set by a version of utag.js prior to 4.27. These values are now reset to 1.

4.27 (February 2014)

  • Introduces support for AudienceStream Data Layer Enrichment. This requires AudienceStream and the DataCloud Tag.
  • The utag.js reads Meta tags with every utag.view call in order to capture dynamic Meta tags.
  • There are several changes to the utag_main cookie:
    • The utag_main cookie’s lifespan is now set to 1 year to conform to EU laws.

    • The session ID (ses_id) value in the utag_main cookie is now a timestamp that is used to compute a visitor’s time on your website.

      To reference this value, use the following syntax:

      b["cp.utag_main_ses_id"]
      
    • Introduces the session number value in the utag_main cookie.

      To reference this value, use the following syntax:

      b["cp.utag_main__sn"]
      
    • Introduces the page number value, which increments every time utag.js loads, essentially with each new URL load. This is not to be confused with an Event Counter. This value starts over at 1 with each new session.

      To reference this value, use the following syntax:

      b["cp.utag_main__pn"]
      
    • Known issue: The page number (_pn) and session number (_sn) values are set to NaN whenever a visitor visits a website in which the utag_main session cookies was already set by a version of utag.js prior to 4.27. This issue is resolved in utag.js version 4.28.

  • Introduces the utag.ut.flatten function, which flattens objects. This is primarily used with Data Layer Enrichment for AudienceStream.

4.26 (January 2014)

Load rules are re-evaluated for both utag.view() and utag.link() calls.

Changes to the way the utag.js 4.26 file handles query string parameters and meta tags means that they are no longer lower-cased by default. If you have query string parameters or meta tags identified as data sources in your profile, you may need to update those data source names in the Data Layer tab to match upper case and lower case letters exactly.

Custom Script Source is a Blocking Tag

A blocking tag is a tag that must run before any other tags run. When you enter the location for the custom script source advanced setting for a tag, this tag automatically becomes a blocking tag. This tag still loads asynchronously, but subsequent asynchronous scripts. For example, utag.10.js does not load until the blocking tag is complete.

Best Practice: If you want to load custom JavaScript for a tag but you do not want it to be a blocking tag, use the Tealium Generic Tag to load it.

Wait Flag Improvement

The Wait Flag is an advanced setting within tag configuration.

Tags whose Wait Flag is set to “No” load and fire immediately after the utag.js file loads. Those tags, whose Wait Flag is set to “No”, that load sooner may fire sooner, regardless of their order in Tealium iQ. For example, if Tag 2 loads before Tag 1, and Tag 1 is placed higher in the Tags tab in Tealium iQ, Tag 2 may still fire sooner, despite the order they’re in. Previously, tags executed in the order specified in Tealium iQ. These tags then waited for tags placed higher in the order to load before loading themselves.

This means that you may now have a mixture of tags with their Wait Flag set to ‘No’ and tags with their Wait Flag set to ‘Yes’ in the same profile.

Control Load Rules-based Tracking for AJAX

Subsequent utag.view() calls on the page trigger load rules to load new tags. In previous versions, a utag.view call does not load new tags. This feature is enabled by default in utag.js 4.26.

Disable this feature to keep current behavior. See utag.cfg.load_rules_ajax flag details below for more information.

A utag.link() call does not load a new tag. Only a utag.view() call does this.

Load a Tag Directly By UID (Update to utag.view and utag.track calls)

For advanced implementations, especially those using AJAX, use the utag.view() call to bring in a new tag and fire it based on the tag’s UID (as seen in the Tags tab of Tealium iQ). This bypasses all load rules.

utag.view({page_name : "New Page"}, null, [5]);
  • Param 1: Data Layer
  • Param 2: Callback function (or null)
  • Param 3: Array of UIDs to load and fire

Learn more about page tracking.

Automatically Read New “Meta” tags

These types of meta tags with “name=” were picked up in a previous version of utag.js:

<meta name="keywords" content="Apple,Tab" />

The new utag.js 4.26 now picks up those with property= (see “Open Graph” meta tags)

<meta property="og:type" content="video.movie" /> 

Removing the “lowercase” by default of “qp.” (query string) and “meta.” variables

This is a logic change in the default behavior of utag.data. Set the utag.cfg.lowerqp flag to true to automatically lowercase. However, the default setting keeps the mixed case.

Set the utag.cfg.lowerqp flag to true for backward compatibility with previous utag.js behavior.

Set the utag.cfg.lowermeta flag to true to enable lower-casing for the meta tags. This only applies to the name of the name/value pair for that meta tag.

If you have mixed-case query string parameters, you need to update the data source’s name in the Data Sources tab to match exactly. Any code that refers to this query string type data source must also be updated.

New Values in utag_main Cookie

There are new cookie name/value pairs in the utag_main cookie:

  • utag_main_vid
    A long string to uniquely identify the visitor, such as 013efdc67183001adeec0eef13010a051001b00f0093c)
  • utag_main__ss
    A “Session Start” flag. Set to "1" for the first page view of a new session. Default session time is 30 minutes elapsed with no activity.

(The previous cookie values utag_main__st and utag_main_ses_id are still set.)

Session Start Tracking

A request for an empty file, utag.v.js, is made once at the start of a visitor’s session. This is used internally by Tealium to log the session count. The HTTP request URL looks like this:

http://tags.tiqcdn.com/utag/tiqapp/utag.v.js?a=tealium/main/201306012057&cb=1370276499302

The new cookie value utag_main__ss, is used to determine when to fire. This is only sent on the first event of a session. This request is sent last, after all tags have fired.

New “Tealium” Values

Identify the new cookie values in the Data Layer tab:

  • The session ID value in the utag_main_ses_id cookie
  • The visitor ID value in the utag_main_v_id cookie
  • The session start flag (0 or 1) found in the utag_main__ss cookie

URL Fragment Parameters

Previously the name/value pairs in a URL after the ? were read and stored in utag.data as qp. values. Now, items after the hash/fragment # sign are also used to build these. This adds an important feature for AJAX sites.

Example Domain URL:(http://www.example.com?param1=value1&param2=value2#hash1=value3)`

Previous:

utag.data = { "qp.param1" : "value1", "qp.param2" : "value2"}

New:

utag.data = { "qp.param1" : "value1", "qp.param2" : "value2", "qp.hash1"  : "value3"}

All Page Data Available to utag.view and utag.link Calls

Previously, utag.view and utag.link calls only knew about the data you passed them. Items like b["qp.campaign"] were not available. Now, all “built-in” data points such as URL, meta, or cookie values are added to the data layer for the utag.link and utag.view calls.

Also, dynamic items that may have changed for AJAX sites (such as b["dom.url"]) are re-built so they use the current value. The current value may be different from the value at the time of the initial landing on an AJAX page.

New Options in utag.cfg

Use a Pre Loader-scoped JavaScript Code Extension and the global variable window.utag_cfg_ovrd.

// JS Code in Preloader Extension
window.utag_cfg_ovrd = {
    "noview"          : true,
    "lowerqp"         : true,
    "load_rules_ajax" : false
};

The following new options are available:

  • utag.cfg.load_rules_ajax
    Set this flag to false when you do not wish to “re-evaluate” load rules for each utag.view and utag.link call. For utag.view, this may also load a new utag.X.js file if it did not load on the initial page view.
  • utag.udoname
    The name of the data object. The utag.js code assumes the data object is a global variable. For example, not an object within another object. By default, this is set to utag_data
  • utag.cfg.load_rules_at_wait
    Set this flag to true when you wish to re-evaluate load rules at Wait (DOM Ready). This enables legacy support where data may have been set after utag.js loads and you want to use this data to fire a Tag set to wait for DOM Ready.
  • utag.cfg.lowerqp
    Set this flag to true if you wish to lowercase your query string name/value pairs. This used to be the default behavior.
  • utag.cfg.lowermeta
    Set this flag to true if you wish to lowercase your meta tags’ names. The value of the name/value pair for the meta tag is not lowercased.
  • utag.cfg.noview
    Set this flag to true if you wish to control when the initial utag.view call is made. This is common for AJAX sites where your application controls the page view event (not the initial page load action.)

Things to Consider

  • Accidentally Firing Multiple Orders - The utag.link and utag.view calls now have all of the “DOM” type of data points available in every call. For example, the query string data such as b["qp.order_id"] is read on the page load and trigger an order event. However, if you fire a utag.link call on that same order page, it also has the b["qp.order_id"] data set and trigger a second order event.

  • For most intuitive behavior, we recommend setting all utag_data values before you load in the utag.js file. And keep utag.cfg.load_rules_at_wait at “false”, which is the default.

  • Be aware that updating to utag.js 4.26 changes the default behavior for lower casing your query string params. Values are no longer automatically lower-cased.

  • “All Tags”-scoped Extensions may or may not run before DOM Ready-scoped extensions. Order is not guaranteed. If you manipulate a data layer element in an All Tags-scoped extension, then it may affect your Content Modification Extension’s criteria.

    Best Practice: Do not modify the original data layer object. If you need to modify a value, use a new variable instead.

Known Issues

  • The Data Layer’s utag_data object becomes a reference to utag.data, and changing one changes the other.
  • IE8 may introduce timing issues if your Data Layer is defined at the end of your <body> element, just before DOM Ready (and the utag.js is already loaded). As a best practice, always declare your utag_data object before you load the utag.js file.

4.006 - 4.011

4.011 (November 2013)

Adding support for Server to Server. There is now a ‘Server to Server’ Advanced Setting that enables a Tag to use the Server to Server functionality.

4.010 (November 2013)

Fixes a bug when using the Tealium Currency Converter tag or any Tag with a value set for Custom Source Advanced setting, in which the Tag waits until for a force timeout threshold of 3 seconds or greater to call the u.send function for the other Tags.

4.009 (September 2013)

Fixes a bug in which “Wait = Yes” tags wait for a “load” event instead of DOM Ready event when utag.js was executed after DOM Ready.

For many sites, this is a significant performance boost and loads tags that are set to wait for DOM Ready much sooner.

4.008 (March 2013)

Update to support domains ending in “.edu.au” and “.net.au” (using “au” for an example.) The previous utag.js only supported “.com.au” and “.org.au”

Update to utag.loader.GV (the internal “Get Variables in Object” function) to use hasOwnProperty. This is the safer way to iterate.

4.007 (January 2013)

Fixes an issue in which the customer may an exception in the “pre” function by entering something like myobj.utag_data for the “Page Data Object” Publish Setting (assuming the myobj doesn’t exist). This exception caused pieces of code to get skipped and resulted in checking .length for a utag.handler.extend variable that was never defined. There is now a check to see if utag.handler.extend is defined.

4.006 (January 2013)

The Publish Engine builds a utag.loader.cfgsort variable that is an Array of the Tag UIDs. This Array is in the right order of the Tags in Tealium iQ. Tags now fire in the order that matches the Tealium iQ’s order.

4.000-4.005

4.005 (December 2012)

Adds the utility function utag.ut.decode.

Also adds support for a “no cookie” flag utag.cfg.nocookie. When the utag.cfg.nocookie value is defined and set to true then utag.js does not write any utag_main cookies.

Existing utag_main cookies are not modified or removed. Some tags expect that utag_main cookies exist, so use this flag at your own risk.

Sample (Pre Loader-scoped JavaScript Code Extension):

var utag_cfg_ovrd={};  
utag_cfg_ovrd.nocookie=true;

utag.ut.decode is a safer version of decodeURIComponent (if decodeURIComponent issues an exception, then unescape is used)

4.004 (November 2012)

Includes a fix for an Internet Explorer DOM Ready Extension “timing” issue in IE7 and IE8 in which IE may or may not run the DOM Ready Extensions before Tags are loaded. This version fixes the issue to ensure that DOM Ready Extensions run first. This provides consistent behavior in all browsers.

Changes in utag.DB. This function is changed so that every utag.DB call does not “re-check” the cookie for utagdb=true; this makes for a high-performance utag.DB function.

Adds additional utag.DB calls in utag.js.

How do you turn on debugging? Run this in a console: document.cookie="utagdb=true"

Sample utag.DB call:

utag.DB("Inside of DOM Ready Extension");

4.003 (October 2012)

Adds the ability to set a utag_main cookie to expire at a specific timestamp.

utag.loader.SC("utag_main",{"mycookie123":"testing123;exp-1351111959896u"});

Note the “u” at the end of the timestamp

4.002 (August 2012)

Runs through the utag.link also for each of the sub profile tags.

4.001 (August 2012)

Fixes a cookie decode issue in which the cookie had strange characters.

4.000 (Initial)

There are multiple iterations of this file with no version number changes.

Was this page helpful?

This page was last updated: January 7, 2023