Best way to find nested property by name in object

Viewed 624

I have an object (dataLayer), which can increase and decrease in length, depending on how many pages you've visited.

I want to:

  • Loop through the objective and look for the property name "ecommerce".
  • I specifically want to find the value of "brandcode".
  • Must be in the same object group as "pagetitle: `Login Page"

Obviously, I can do dataLayer['4'].ecommerce.information. product. However, the problem I have this that this key/value position could be at any number. EG dataLayer[0],[1],[2],[12] etc

What is the best way to loop through this object and look for this key/value pair, regardless of it's index in the object?

const dataLayer = 
  { 0: { a: 123, event: 'pageload', productId: 1 } 
  , 1: { b: 456, event: 'pageload', productId: 3 } 
  , 2: {         event: 'gtm.load', productId: 3 } 
  , 3: {         event: 'gtm.load', productId: 4 } 
  , 4: 
    { pagetitle: 'Login Page'
    , ecommerce: 
      { information: 
        { product: 
          [ { brandCode: 'car', productColor: 'red' } 
          , { brandCode: 'car', productColor: 'green' } 
          , { brandCode: 'car', productColor: 'yello' } 
          ]   
  } } } };

Thanks,

3 Answers

this way with for( of ) and for( in )

const dataLayer = 
  { 0: { a: 123, event: 'pageload', productId: 1 } 
  , 1: { b: 456, event: 'pageload', productId: 3 } 
  , 2: {         event: 'gtm.load', productId: 3 } 
  , 3: {         event: 'gtm.load', productId: 4 } 
  , 4: 
    { pagetitle: 'Login Page' , fx:false, trduc: { madchin: 'bidule'}
    , ecommerce: 
      { information: 
        { product: 
          [ { brandCode: 'car', productColor: 'red'   } 
          , { brandCode: 'car', productColor: 'green' } 
          , { brandCode: 'car', productColor: 'yello' } 
          ]   
  } } } }
  ;
for (let key in dataLayer) // key value are '0','1',...,'4'
  {
  if ( 'ecommerce' in dataLayer[key]
    && dataLayer[key]?.pagetitle==='Login Page'
    ) {
    for (let prod of dataLayer[key].ecommerce.information.product)
      {
      console.log( prod.brandCode, prod.productColor )
  } } }
.as-console-wrapper { max-height: 100% !important; top: 0; }

[edit]

I have added a verification on pagetitle==='Login Page' see Optional chaining (?.)
and corrected the test on the existence of the ecommerce property see in operator

To retrieve an array of brandcodes from specifically "Login Page"

const dataLayer = {
  0: {event: 'pageload', productId: 1, a: 123},
  1: {event: 'pageload', productId: 3, b: 456},
  2: {event: 'gtm.load', productId: 3},
  3: {event: 'gtm.load', productId: 4},
  4: {
    pagetitle: 'Login Page',
    ecommerce: {
      information: {
        product: [
          {brandCode: 'car', productColor: 'red'},
          {brandCode: 'truck', productColor: 'green'},
          {brandCode: 'bike', productColor: 'yello'},
        ]
      }
    }
  },
  17: {
    pagetitle: 'Login Page',
    ecommerce: {
      information: {
        product: [
          {brandCode: 'cow', productColor: 'lila'},
        ]
      }
    }
  }
};


function getEcommerceBrandCodes(pagetitle, data) {
  return Object.entries(data).reduce((a, [k, ob]) => {
    const isPagetitle = ob.hasOwnProperty("pagetitle") && ob.pagetitle === pagetitle;
    const isEcommerce = ob.hasOwnProperty("ecommerce");
    if (isPagetitle && isEcommerce) {
      a.push(ob.ecommerce.information?.product?.map(item => item.brandCode));
    }
    return a;
  }, []).flat();
}

console.log(getEcommerceBrandCodes("Login Page", dataLayer));

I had to strip out ES6, as the tool I'm using only allows ES5. But with this solution, I can take the last entry/update of ecommerce.information to the dataLayer, by adding it into a new array and then slicing the last entry.

var productArray = [];

for (var i = 0; i < dataLayer.length; i++) {
    if (dataLayer[i].ecommerce) {
        for (var line in dataLayer[i].ecommerce.information) {
            var itemProducts = dataLayer[i].ecommerce.information;
            productArray.push(itemProducts);
        };
    };
};

var lastItem = productArray.slice(-1);

if (lastItem[0].product[0].brandCode === "car") {
    //do something
} else {
    //do something
}

Roko C. Buljan's solution is also helpful, as this is isolated to the pagetitle, which I will also playaround with as well.

Thanks everyone!

Related