Copy Google Analytics custom definitions/dimensions between GA4 properties with the Google Analytics Data API?

1.3k views Asked by At

I have a number of GA4 Google Analytics properties that need to share the same custom dimensions (custom definitions). Using the web UI to manually copy them is slow and error prone. How can I automate this process?

Using Google Apps Script and the Google Analytics Data API v1 I've created a function that almost does it:

https://script.google.com/d/1Tcf7L4nxU5zAdFiLB2GmVe2R20g33aiy0mhUd8Y851JLipluznoAWpB_/edit?usp=sharing

However the API is in beta and doesn't seem to have a way to add the dimensions to the destination GA property.

Does anyone have a way to complete this final step?

function main(){
  gaSourcePropertyId = '12345678';
  gaDestinationPropertyId = '87654321';
  copyCustomDefinitions(gaSourcePropertyId, gaDestinationPropertyId);
}

function copyCustomDefinitions(gaSourcePropertyId, gaDestinationPropertyId) {
  let sourceDimensions = getCustomDimensions(gaSourcePropertyId);
  addCustomDimensions(gaDestinationPropertyId, sourceDimensions);
}

function getCustomDimensions(gaPropertyId) {
  var sourceDimensions = AnalyticsData.Properties.getMetadata(`properties/${gaPropertyId}/metadata`)['dimensions'];
  var sourceCustomDefinitions = [];
  sourceDimensions.forEach((dimension)=>{
    if (dimension['customDefinition'] == true){ sourceCustomDefinitions.push(dimension)}
  });
  return sourceCustomDefinitions;
}

function addCustomDimensions(gaPropertyId, dimensions) {
  const destinationDimensions = getCustomDimensions(gaPropertyId);
  const destinationDimensionApiNames = destinationDimensions.map(dimension=>dimension['apiName']);
  dimensions.forEach((dimension)=>{
    // Check if the new dimension already exists in the destination.
    if ( !destinationDimensionApiNames.includes(dimension['apiName']) ) {

      let newDimension = AnalyticsData.newDimension(dimension['apiName']); // The newDimension method doesn't seem to work yet!
      // TODO - add the dimension to the destination property
      console.warn('There is not yet an API function for adding dimensions to a property. Something like AnalyticsData.Properties.setMetadata is needed!');

    } else {
      console.info(`Dimension with apiName '${ dimension['apiName'] }' already present in destination! Dimension not added to destination`);
    }
  })
  
}




1

There are 1 answers

1
nutcracker On

Turns out there is the Google Analytics Admin API which provides methods for manipulating the custom dimensions of a property.

This includes functions for listing custom dimensions and creating custom dimensions

function main(){
  gaSourcePropertyId = '1234';
  gaDestinationPropertyId = '4321'; 
  copyCustomDimensions(gaSourcePropertyId, gaDestinationPropertyId);
}

function copyCustomDimensions(gaSourcePropertyId, gaDestinationPropertyId) {
  let sourceDimensions = getCustomDimensions(gaSourcePropertyId);
  addCustomDimensions(gaDestinationPropertyId, sourceDimensions);
}

function getCustomDimensions(gaPropertyId) {
  try {
    return AnalyticsAdmin.Properties.CustomDimensions.list(`properties/${gaPropertyId}`)['customDimensions'];
  } catch (error) {
    console.error(error);
  }
}

function addCustomDimensions(gaPropertyId, dimensions) {
  let destinationCustomDimensions = getCustomDimensions(gaPropertyId);

  // The destination may not have any custom dimensions.
  if (typeof destinationCustomDimensions == 'undefined') {
    console.info(`Could not get custom definitions for property ID '${gaPropertyId}'.`, destinationCustomDimensions);
    destinationCustomDimensions = [];
  };

  const destinationDimensionParameterNames = destinationCustomDimensions.map(dimension=>dimension['parameterName']);
  
  dimensions.forEach((sourceDimension)=>{
    // Check if the new dimension already exists in the destination.
    if ( !destinationDimensionParameterNames.includes(sourceDimension['parameterName']) ) {
      let destinationDimension = { 
        "parameterName": sourceDimension['parameterName'], 
        "displayName": sourceDimension['displayName'], 
        "description": sourceDimension['description'], 
        "scope": sourceDimension['scope']
      };
      let result = null;
      try {
        result = AnalyticsAdmin.Properties.CustomDimensions.create(destinationDimension, `properties/${gaPropertyId}`);
        console.log('[COPIED]',result);
      } catch (error) {
        console.log('[FAILED]', destinationDimension)
        console.error(error);
      }
      
    } else {
      console.info(`[NO ACTION] Dimension with apiName '${ sourceDimension['parameterName'] }' already present in destination! Dimension not added to destination.`, sourceDimension);
    }
  });
  
}