Module 5: Competition And Market
The strategic 2×2 map: how to choose axes that truly discriminate
Description
Since lesson 1 you've been using competitiveMap's 2×2 map without stopping to ask a question this lesson answers head-on: why those two axes —catalog breadth and curation depth— and not any other two? Not just any pair of axes produces a useful map. A 2×2 with the wrong axes can look just as professional as a well-built one —the four quadrants, the grid, the players carefully placed— and yet say absolutely nothing, because the chosen axes don't distinguish between the players in any way that matters. This lesson teaches you to recognize the difference before trusting any map.
Connection to the module. Lessons 2 through 5 took it for granted that breadth and curation were the right axes for Mercado's case — and they are, because they're literally the two axes of the strategy Mercado chose back in module 2. This lesson makes explicit the criterion behind that choice, so you can apply it to any new map you build, not just Mercado's. Lesson 7 takes this same criterion and flips it around: what happens when the chosen axes, even though they do discriminate, are no longer the axes of the battle that matters.
An everyday analogy: the thermometer and the blood pressure cuff
At a medical checkup, the doctor takes your temperature and also measures your blood pressure — two numbers, two different instruments. Each one measures something the other can't see: temperature says nothing about your blood pressure, and blood pressure says nothing about whether you have a fever. Together, the two numbers give the doctor a much richer reading than either one alone, precisely because they're independent — each contributes information the other doesn't have.
Now imagine a doctor who, instead, takes your temperature twice with two different thermometers, and calls that "a complete two-measurement checkup." Technically they took two measurements — but both are going to tell you almost the same thing, because they measure the same thing with different instruments. They learned nothing they didn't already know from the first measurement. A 2×2 map with axes that don't discriminate is exactly that second doctor: it looks more rigorous for having two axes instead of one, but if both axes end up grouping everyone the same way, the second axis added no new information — it's a repeated thermometer, disguised as a blood pressure cuff.
Worked example: two maps of the same roster, two very different results
We run competitiveMap twice on exactly the same roster of four players — but with two different pairs of axes. The first pair (hasApp × foundedRecently) sounds like a reasonable "product" analysis at first glance. The second pair is the one you've been using since lesson 1 (breadth × curation):
// Pedagogical model: places each player on a 2x2 map along two
// STRATEGIC axes (not objective market metrics) and flags whether
// "our" quadrant is open -- the space where Mercado can win without
// running head-on into another player.
function competitiveMap(us, players, axes) {
const [xAxis, yAxis] = axes;
const place = (player) => {
const xSide = player.scores[xAxis.key] >= xAxis.midpoint ? xAxis.high : xAxis.low;
const ySide = player.scores[yAxis.key] >= yAxis.midpoint ? yAxis.high : yAxis.low;
return `${ySide} / ${xSide}`;
};
const usQuadrant = place(us);
const placed = players.map((p) => ({
name: p.name,
type: p.type,
quadrant: place(p),
sharesQuadrantWithUs: place(p) === usQuadrant,
}));
const openSpace = !placed.some((p) => p.sharesQuadrantWithUs);
return { us: { name: us.name, quadrant: usQuadrant }, players: placed, openSpace };
}
const players = [
{ name: 'MegaStoreGenerico', type: 'direct', scores: { breadth: 9, curation: 2, hasApp: 1, foundedRecently: 0 } },
{ name: 'TiendasLocalesOnline', type: 'indirect', scores: { breadth: 3, curation: 4, hasApp: 1, foundedRecently: 0 } },
{ name: 'NicheHandmadeMarketplace', type: 'indirect', scores: { breadth: 3, curation: 8, hasApp: 1, foundedRecently: 1 } },
{ name: 'JustSearchOnGoogle', type: 'substitute', scores: { breadth: 10, curation: 1, hasApp: 1, foundedRecently: 0 } },
];
const us = { name: 'Mercado', scores: { breadth: 8, curation: 8, hasApp: 1, foundedRecently: 0 } };
const badAxes = [
{ key: 'hasApp', label: 'has a mobile app', low: 'no', high: 'yes', midpoint: 1 },
{ key: 'foundedRecently', label: 'founded after 2020', low: 'no', high: 'yes', midpoint: 1 },
];
const badMap = competitiveMap(us, players, badAxes);
console.log('=== competitiveMap with axes that do NOT discriminate (hasApp x foundedRecently) ===\n');
console.log(`[us] ${badMap.us.name} -> quadrant: "${badMap.us.quadrant}"`);
console.table(badMap.players);
console.log(`openSpace: ${badMap.openSpace}`);
const axesDiscovery = [
{ key: 'breadth', label: 'catalog breadth', low: 'niche', high: 'broad', midpoint: 5 },
{ key: 'curation', label: 'curation depth', low: 'raw-search', high: 'curated', midpoint: 5 },
];
const goodMap = competitiveMap(us, players, axesDiscovery);
console.log('\n=== competitiveMap with axes that DO discriminate (breadth x curation) ===\n');
console.log(`[us] ${goodMap.us.name} -> quadrant: "${goodMap.us.quadrant}"`);
console.table(goodMap.players);
console.log(`openSpace: ${goodMap.openSpace}`);
What to expect. Running the file with Node produces exactly this output:
=== competitiveMap with axes that do NOT discriminate (hasApp x foundedRecently) ===
[us] Mercado -> quadrant: "no / yes"
┌─────────┬────────────────────────────┬──────────────┬─────────────┬──────────────────────┐
│ (index) │ name │ type │ quadrant │ sharesQuadrantWithUs │
├─────────┼────────────────────────────┼──────────────┼─────────────┼──────────────────────┤
│ 0 │ 'MegaStoreGenerico' │ 'direct' │ 'no / yes' │ true │
│ 1 │ 'TiendasLocalesOnline' │ 'indirect' │ 'no / yes' │ true │
│ 2 │ 'NicheHandmadeMarketplace' │ 'indirect' │ 'yes / yes' │ false │
│ 3 │ 'JustSearchOnGoogle' │ 'substitute' │ 'no / yes' │ true │
└─────────┴────────────────────────────┴──────────────┴─────────────┴──────────────────────┘
openSpace: false
=== competitiveMap with axes that DO discriminate (breadth x curation) ===
[us] Mercado -> quadrant: "curated / broad"
┌─────────┬────────────────────────────┬──────────────┬──────────────────────┬──────────────────────┐
│ (index) │ name │ type │ quadrant │ sharesQuadrantWithUs │
├─────────┼────────────────────────────┼──────────────┼──────────────────────┼──────────────────────┤
│ 0 │ 'MegaStoreGenerico' │ 'direct' │ 'raw-search / broad' │ false │
│ 1 │ 'TiendasLocalesOnline' │ 'indirect' │ 'raw-search / niche' │ false │
│ 2 │ 'NicheHandmadeMarketplace' │ 'indirect' │ 'curated / niche' │ false │
│ 3 │ 'JustSearchOnGoogle' │ 'substitute' │ 'raw-search / broad' │ false │
└─────────┴────────────────────────────┴──────────────┴──────────────────────┴──────────────────────┘
openSpace: true
Same roster of four players, same function, two opposite conclusions. With hasApp × foundedRecently, three players that are completely different from each other —a giant megastore, a network of neighborhood shops, and a search engine that isn't even an e-commerce company— land in exactly the same quadrant as Mercado. The result (openSpace: false) tells you absolutely nothing useful, because almost any modern digital player "has an app": that axis doesn't separate anyone from anyone. It's the repeated thermometer from the analogy — it looks like a second axis, but it contributes no real distinction. With breadth × curation, on the other hand, the same four players spread across three different quadrants, and Mercado's is clearly open — because these two axes do capture a real difference in strategy between the players.
Deep dive: the two-independent-axes test
Before trusting any 2×2 map, apply this three-question test to the axes you're about to use:
- Does the axis actually separate the players, or does almost everyone fall on the same side? If nine out of ten players in your category share the same value on an axis (like "has an app" in this lesson's example), that axis isn't discriminating anything — it's nearly constant, and a nearly constant variable contributes no information.
- Do the two axes measure genuinely different things, or are they the same idea with a different name? A "product quality" axis and a "customer satisfaction" axis often move together —if one goes up, the other almost always goes up too— and end up functioning as a single axis disguised as two. Useful axes can usually move in opposite directions: a player can be broad and uncurated (
MegaStoreGenerico), or narrow and curated (NicheHandmadeMarketplace) — all four combinations are possible, not just two. - Does the axis connect to a real strategic choice, or is it just an easy piece of data to get?
hasAppis easy to verify with a five-minute search — that's exactly why it's tempting to use. But ease of measurement isn't the same as strategic relevance. The right axes are the ones that reflect the choice the strategy made (in Mercado's case, from module 2: curated discovery instead of low price, broad catalog instead of narrow niche), not the ones closest at hand.
A map that passes all three questions doesn't guarantee the strategy is correct — but it guarantees the map is at least capable of showing you the truth if the strategy were wrong. A map that fails all three can't show you anything, good or bad, because it doesn't distinguish.
Common mistakes
Building a 2×2 with axes that don't discriminate. What happens: two axes are chosen because they're easy to measure or sound professional in a presentation —like hasApp or foundedRecently— without first checking whether they actually separate the players in a useful way, and the resulting map groups completely different rivals into the same quadrant, generating nonsensical conclusions (like in this example: a megastore, a network of neighborhood shops, and a generic search engine "competing in the same quadrant" as Mercado). Why it happens: any pair of axes produces a grid that looks rigorous, and that visual appearance gets confused with real validity, without anyone stopping to ask whether the axis discriminates. How to spot it: apply this lesson's two-independent-axes test before presenting any map — if more than two-thirds of the players land in the same quadrant, the axis probably isn't discriminating. How to fix it: replace any axis that fails the test with one anchored in a real strategic choice, as you did moving from hasApp to curation.
Choosing axes for ease of measurement, not strategic relevance. What happens: the team ends up using data it already had on hand —company age, whether it has some specific feature, headcount— simply because getting that data is fast, even though it has no relationship to the strategy being evaluated. Why it happens: collecting the right data point sometimes requires judgment and estimation (like curation, which doesn't appear in any public report), while the easy data point comes ready-made — and convenience quietly beats relevance. How to spot it: ask yourself, for each candidate axis, "does this axis appear in our strategy's definition (module 2), or does it only appear in the data sheet we already had?" How to fix it: always start from the strategy's exact words —"where to play" and "how to win"— and turn those words into axes, even if that means estimating the values with judgment instead of copying them from a database.
Trusting a 2×2 map without checking whether the axes are independent of each other. What happens: two axes are chosen that, without anyone noticing, tend to move together —for example, "perceived quality" and "premium pricing"— and the map ends up showing only two of the four possible quadrants occupied, giving the false impression that there's less strategic variety than actually exists. Why it happens: two correlated axes don't look different from two independent axes at the moment they're chosen —the problem only becomes visible afterward, when the resulting map has empty quadrants that "shouldn't be empty." How to spot it: if, after placing all the players, two of the four quadrants end up completely empty and nobody can explain why no player —not even a hypothetical one— could occupy those combinations, be suspicious of the axes. How to fix it: before building the map, ask whether it's conceptually possible for a player to be high on one axis and low on the other, and vice versa — if you can't imagine such a player, the axes are probably measuring the same thing.
Exercises
Exercise 1 — Diagnose an axis without running the code. A colleague proposes mapping the competitive landscape using the axes "headquartered in the same city as Mercado" and "accepts credit card payments." Apply this lesson's two-independent-axes test and explain, in a paragraph, why neither one probably works.
See solution
Both axes fail the "does the axis actually separate the players?" test: in today's e-commerce, the vast majority of relevant platforms accept credit cards —that axis is going to group almost everyone on the same side, exactly like what happened with hasApp in the lesson's example—, and "headquartered in the same city" probably doesn't matter either for a digital marketplace, which doesn't compete on the geographic proximity of its offices but on catalog reach and trust. Neither axis connects to a real strategic choice made by Mercado (curation, breadth, local trust in the seller, not in the company's location) — they're data points that are easy to get, but irrelevant to the question the map needs to answer.
Exercise 2 — Propose a valid third pair of axes. In addition to breadth × curation, propose another pair of axes that could also be useful for mapping the same Mercado landscape, and mentally verify it passes this lesson's three-question test.
See solution
A reasonable pair: priceSensitivity (how oriented toward low price the player is) × sellerTrustDepth (how deep the trust relationship with the seller is, beyond just "has a verified profile"). It passes the test: (1) it discriminates — a player can be price-aggressive with a shallow seller relationship (MegaStoreGenerico) or price-careful with a deep one (TiendasLocalesOnline), all four combinations are plausible; (2) they're independent — there's no reason low price and deep seller trust should rise or fall together; (3) they connect to strategy — modules 2 and 4 explicitly talk about "trust in local sellers" as part of Mercado's differentiation, so this axis reflects a real choice, not a convenient data point.
Exercise 3 — Explain the result to someone who only saw the bad map. A stakeholder only saw the map with hasApp × foundedRecently (where openSpace: false) and concluded that Mercado has no space of its own in the market. Write, in a paragraph, how you'd explain that this conclusion depends entirely on the chosen axes, without sounding like you're dismissing the finding just because you don't like it.
See solution
A sample answer: "It's true that with those two axes the result says there's no open space — but before accepting that conclusion, we need to ask how well those axes distinguish between the players. hasApp groups a giant megastore, a network of neighborhood shops, and a generic search engine into the same quadrant as us — three completely different businesses, joined only because all four 'have an app,' something almost any digital player has today. That axis isn't measuring anything strategic, just something so common it doesn't separate anyone. When we use the axes that actually reflect our real strategy —catalog breadth and curation depth— the same roster of players spreads across three different quadrants, and ours is clearly open. We're not dismissing the first map because we don't like the result — it's that that map, with those axes, had no way of telling us anything useful, for or against."
Summary and next step
This lesson formalized the criterion behind the instrument you've been using since lesson 1: a 2×2 map is only useful if its axes discriminate between players, are independent of each other, and connect to a real strategic choice, not a convenient data point. You saw the same roster produce opposite conclusions —openSpace: false with trivial axes, openSpace: true with strategic axes— without a single player or a single line of the function changing.
Before moving on you should be able to: apply the two-independent-axes test to any pair of axes before trusting a 2×2 map, and explain why "the map looks rigorous" isn't the same as "the map says something true."
You now know how to choose axes that discriminate today. Lesson 7 introduces a different, subtler danger: axes that discriminated perfectly well — but in yesterday's battle, not today's.
Resources
- Ben Thompson, "Aggregation Theory" — stratechery.com/2015/aggregation-theory. Thompson builds much of his competitive analysis by very carefully choosing the right axes (control of the user relationship, marginal cost of serving one more user) — a real example of this lesson's discipline applied to entire digital markets. In English.
- Jeff Jordan (a16z), "So You Want to Compete Against Amazon?" — a16z.com/so-you-want-to-compete-against-amazon. Jordan explicitly names "curation" as a competitive axis distinct from —and more defensible than— price or catalog, the same pair of axes you used in this lesson's example. In English.