Converting an object to be used with a treegrid
I believe this does the same as yours, except it uses buildLeaf on each step (your function skips it in the "middle" loop, and just makes an empty object).

// Recursive convertion function
function convert(obj) {
  var item, leaf, key, leaves = [];
  for( key in obj ) {
    if( !obj.hasOwnProperty(key) ) continue;
    item = obj[key];
    leaf = buildLeaf(key, item)
    leaves.push(leaf);
    if( typeof item.children === 'object' ) {
      leaf.children = convert(item.children);
    }
  }
  return leaves;
}

// I also refactored buildLeaf slightly to accept both
// name and content, and to make use of JavaScript's
// `||`-style fallbacks

function buildLeaf(name, node) {
  var leaf        = { name: name, children: [] },
      clicks      = node.clicks || 0,
      conversions = node.conversions || 0,
      earned      = node.earned || 0,
      spent       = node.spent || 0;

  leaf.clicks          = clicks;
  leaf.conversions     = conversions;
  leaf.earned          = '$' + earned.toFixed(2);
  leaf.spent           = '$' + spent.toFixed(2);
  leaf.conversion_rate = conversionRate(conversions,clicks);
  leaf.net_earned      = netEarned(earned,spent);
  leaf.epc             = epc(clicks,earned,spent);
  leaf.roi             = roi(earned,spent);

  return leaf;
}

// In the calculation functions, I made the value checking
// less strict. Generally, strong checking is encouraged,
// but in this case other useless values would slip through,
// when only strongly checking for zero (since that allows
// `false`, empty strings, etc. to pass through).

function conversionRate(cv, cl) {
  if( !cl ) return '0%';
  return ((cv/cl)*100).toFixed(1) + '%';
}

function epc(cl, e, s) {
  if( !cl || !e ) return '$0.000';
  return '$' + ((e - (cl * s)) / cl).toFixed(3);
}

function netEarned(e, s) {
  if( !e ) return '$0.00';
  return '$' + (e - s).toFixed(2);
}

function roi(e, s) {
  if( !e ) return '0%';
  return (((e - s) / s) * 100).toFixed(0) + '%';
}




Addendum

If you need to handle the conversion differently for different levels of nesting (re: the comments), you could do something like this

function convert(obj) {
  // get the extra, optional, argument.
  // It defaults to 1, and increments otherwise
  var level = (arguments[1] || 0) + 1;

  var item, leaf, key, leaves = [];
  for( key in obj ) {
    if( !obj.hasOwnProperty(key) ) continue;
    item = obj[key];
    // Check the level here
    if( level === 2 ) {
      // 2nd level will only be converted to a simpler, non-leaf object
      leaf = { name: key, children: [] };
    } else {
      // Other levels will become "leaves"
      leaf = buildLeaf(key, item);
    }
    leaves.push(leaf);
    if( typeof item.children === 'object' ) {
      // remember to pass the level on
      leaf.children = convert(item.children, level);
    }
  }
  return leaves;
}


I don't know if there's a system in the data you're converting, but you could also check for level % 2 === 0 to handle every second (i.e. even-numbered) level differently.