Making a Mark with RedMart

As reported in AsiaOne on 15 April 2016 by Amrita Kaur. More details can be found here.

Vikram Rupani and Roger Egan III were classmates doing their master of business administration in entrepreneurship and marketing at INSEAD in 2010. They lived near the institute and often did grocery shopping in the one-north area. At that time, there was only one supermarket there. The supermarket didn’t have the entire range of products and it was hard for the two to lug the bags of groceries home, as they didn’t have cars.

They thought that facing such a problem here didn’t make sense as Singaporeans are tech-savvy, the country has a high Internet penetration rate and groceries are a necessity in every household. The duo, who were customers of online grocery shopping website FreshDirect when they were living in New York previously, also understood the convenience of getting household products delivered to their doorstep.

/** * helper function to take the form and * get back a js object with field/value mappings * ignoring submit fields and fields whose name we can't ascertain */ function serialize(form){ return .filter(isInputElement) .filter(isNotSubmit) .filter(hasFieldName) .reduce(function(data, node, index) { data[getFieldName(node)] = node.value return data; }, {}); } /** * Check if this form element is of type input */ function isInputElement(node) { return node.tagName.toLowerCase() === 'input'; } /** * Check if this is a 'submit' input element */ function isNotSubmit(node) { return node.type !== 'submit'; } /** * Ensure field has a derived name */ function hasFieldName(node) { return getFieldName(node) !== 'unknown'; } /** * Attempt to ascertain "name" of field. * * they don't give inputs real `name` attributes, so * best guess is to hack around the element's label text, * falling back to the placeholder text. (their html is * not semantic and often labels erroneously reference * parent divs instead of sibling input elements) * * strip out the stars they show when validation fails * * if label is misplaced _and_ there's no placeholder, * this function is insufficient */ function getFieldName(input) { if (!input.labels.length) return input.placeholder || 'unknown'; var labelText = input.labels[0].textContent.trim(); return ~labelText.indexOf(' *') ? labelText.slice(0, labelText.indexOf(' *')) : labelText; } /** * Listen for form submissions and send identify * if you'd like an event too, just delete the '//' in the track line */ document.forms[0].addEventListener('submit', function(e) { analytics.identify(serialize(; // analytics.track('Submitted Form'); });