Módulo 8: Project Define Mercados Strategy

Dónde jugar

Descripción

La segunda capa del one-pager responde la primera elección real de la cascada: ¿para quién es Mercado, y quién gana en ese terreno? Esta lección no redefine el segmento ni el posicionamiento —eso ya lo hiciste en el módulo 3, con seis lecciones completas dedicadas a esa pregunta—, corre positionFit sobre el caso exacto que ya construiste ahí: el segmento elegido (explorers), el segmento explícitamente excluido (exactSkuShoppers), y las dos alternativas reales (genericMegastore, localShop). El resultado llena la capa whereToPlay del one-pager.

Conexión con el módulo. Esta lección reutiliza positionFit verbatim del módulo 3, sin ningún cambio en la fórmula ni en los datos. Lo único nuevo es el lugar donde vive el resultado: ya no es un ejercicio aislado de ese módulo, es la segunda pieza fija de un documento que, al final de este módulo, va a encadenar cuatro modelos distintos en una sola corrida.

Una analogía cotidiana: el terreno antes que el plan de juego

Ningún entrenador de fútbol diseña la táctica del partido antes de saber en qué cancha va a jugar — si el campo es de césped natural mojado por la lluvia o sintético seco, si es angosto o ancho, cambia por completo qué estrategia tiene sentido. "Dónde jugamos" no es una pregunta retórica ni una formalidad antes de la parte "interesante" — es el dato que determina qué tácticas siquiera son viables. Un equipo que practicó toda la semana un plan de juego para cancha ancha y llega a un campo angosto no puede simplemente ejecutar el mismo plan con más esfuerzo: el terreno cambió las reglas del juego que puede jugar bien.

Esta capa del one-pager es exactamente esa inspección del terreno, hecha con números en vez de con la vista: positionFit confirma, con datos verificables, en qué cancha exacta Mercado gana —y en cuál, con total honestidad, pierde—, antes de que cualquier decisión de "cómo ganar" (la siguiente lección) tenga sentido.

Ejemplo trabajado: el segmento elegido gana, el excluido pierde

Corremos positionFit dos veces sobre los mismos datos del módulo 3: primero contra el segmento que Mercado eligió servir (explorers), después contra el segmento que decidió explícitamente no perseguir (exactSkuShoppers), ambos frente a las mismas dos alternativas.

function positionFit(target, product, alternatives) {
  const dims = Object.keys(target.weights).filter((d) => target.weights[d] > 0);
  const weightedScore = (c) => dims.reduce((sum, d) => sum + target.weights[d] * c.scores[d], 0);
  const productScore = weightedScore(product);
  const rivals = alternatives.map((a) => ({ name: a.name, score: weightedScore(a) }));
  const bestRival = rivals.reduce((a, b) => (b.score > a.score ? b : a));
  const byDimension = dims.map((d) => {
    const rivalBest = alternatives.reduce(
      (best, a) => (a.scores[d] > best.score ? { name: a.name, score: a.scores[d] } : best),
      { name: alternatives[0].name, score: -Infinity }
    );
    return { dimension: d, weight: target.weights[d], productScore: product.scores[d], bestRivalScore: rivalBest.score, bestRivalName: rivalBest.name, wins: product.scores[d] > rivalBest.score };
  });
  return { segment: target.name, productWeightedScore: Number(productScore.toFixed(2)), bestRival: bestRival.name, bestRivalWeightedScore: Number(bestRival.score.toFixed(2)), fitsSegment: productScore > bestRival.score, byDimension };
}

const mercado = { name: 'Mercado', scores: { curatedDiscovery: 9, sellerTrust: 8, catalogBreadth: 6, price: 5, deliverySpeed: 5, convenience: 6 } };
const genericMegastore = { name: 'genericMegastore', scores: { curatedDiscovery: 3, sellerTrust: 4, catalogBreadth: 9, price: 8, deliverySpeed: 9, convenience: 8 } };
const localShop = { name: 'localShop', scores: { curatedDiscovery: 6, sellerTrust: 9, catalogBreadth: 2, price: 4, deliverySpeed: 3, convenience: 3 } };
const alternatives = [genericMegastore, localShop];

const explorers = { name: 'explorers', weights: { curatedDiscovery: 0.4, sellerTrust: 0.3, catalogBreadth: 0.1, price: 0.1, deliverySpeed: 0.05, convenience: 0.05 } };

const positioningStatement = {
  targetSegment: 'compradores que exploran sin saber exactamente qué buscan',
  need: 'se cansan de repetir la misma búsqueda en un buscador genérico y solo encontrar más de lo mismo',
  productCategory: 'el marketplace de descubrimiento curado',
  keyBenefit: 'te sorprende con algo que no sabías que querías, respaldado por vendedores locales de confianza',
  competitiveAlternative: 'un megastore genérico, optimizado para que encuentres rápido lo que ya sabes que quieres',
  differentiator: 'Mercado optimiza para el momento en que todavía no sabes qué es lo que quieres',
};

console.log('=== whereToPlay: positionFit del segmento elegido ===\n');
const whereToPlay = positionFit(explorers, mercado, alternatives);
console.log(`segment: ${whereToPlay.segment} | productWeightedScore: ${whereToPlay.productWeightedScore} | bestRival: ${whereToPlay.bestRival} (${whereToPlay.bestRivalWeightedScore}) | fitsSegment: ${whereToPlay.fitsSegment} | margin: ${(whereToPlay.productWeightedScore - whereToPlay.bestRivalWeightedScore).toFixed(2)}\n`);
console.table(whereToPlay.byDimension.map((d) => ({ dimension: d.dimension, weight: d.weight, product: d.productScore, bestRival: `${d.bestRivalName}:${d.bestRivalScore}`, wins: d.wins })));

console.log('\n=== El positioning statement completo (las 5 piezas de Dunford) ===\n');
console.log(`Para ${positioningStatement.targetSegment}, que ${positioningStatement.need}, Mercado es ${positioningStatement.productCategory} que ${positioningStatement.keyBenefit}. A diferencia de ${positioningStatement.competitiveAlternative}, ${positioningStatement.differentiator}.`);

Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:

=== whereToPlay: positionFit del segmento elegido ===

segment: explorers | productWeightedScore: 7.65 | bestRival: localShop (6) | fitsSegment: true | margin: 1.65

┌─────────┬────────────────────┬────────┬─────────┬──────────────────────┬───────┐
│ (index) │     dimension      │ weight │ product │      bestRival       │ wins  │
├─────────┼────────────────────┼────────┼─────────┼──────────────────────┼───────┤
│    0    │ 'curatedDiscovery' │  0.4   │    9    │    'localShop:6'     │ true  │
│    1    │   'sellerTrust'    │  0.3   │    8    │    'localShop:9'     │ false │
│    2    │  'catalogBreadth'  │  0.1   │    6    │ 'genericMegastore:9' │ false │
│    3    │      'price'       │  0.1   │    5    │ 'genericMegastore:8' │ false │
│    4    │  'deliverySpeed'   │  0.05  │    5    │ 'genericMegastore:9' │ false │
│    5    │   'convenience'    │  0.05  │    6    │ 'genericMegastore:8' │ false │
└─────────┴────────────────────┴────────┴─────────┴──────────────────────┴───────┘

=== El positioning statement completo (las 5 piezas de Dunford) ===

Para compradores que exploran sin saber exactamente qué buscan, que se cansan de repetir la misma búsqueda en un buscador genérico y solo encontrar más de lo mismo, Mercado es el marketplace de descubrimiento curado que te sorprende con algo que no sabías que querías, respaldado por vendedores locales de confianza. A diferencia de un megastore genérico, optimizado para que encuentres rápido lo que ya sabes que quieres, Mercado optimiza para el momento en que todavía no sabes qué es lo que quieres.

Mercado gana el segmento explorers por un margen de +1.65, perdiendo cuatro de seis dimensiones individuales y ganando solo en curatedDiscovery — pero esa única dimensión pesa 0.4, más que las otras cinco juntas. Ahora corre el mismo modelo contra el segmento que Mercado decidió no perseguir:

const exactSkuShoppers = { name: 'exactSkuShoppers', weights: { curatedDiscovery: 0, sellerTrust: 0, catalogBreadth: 0.1, price: 0.35, deliverySpeed: 0.35, convenience: 0.2 } };

console.log('=== whereToPlay: el segmento EXCLUIDO, ¿de verdad pierde? ===\n');
const excluded = positionFit(exactSkuShoppers, mercado, alternatives);
console.log(`segment: ${excluded.segment} | productWeightedScore: ${excluded.productWeightedScore} | bestRival: ${excluded.bestRival} (${excluded.bestRivalWeightedScore}) | fitsSegment: ${excluded.fitsSegment} | margin: ${(excluded.productWeightedScore - excluded.bestRivalWeightedScore).toFixed(2)}\n`);
console.table(excluded.byDimension.map((d) => ({ dimension: d.dimension, weight: d.weight, product: d.productScore, bestRival: `${d.bestRivalName}:${d.bestRivalScore}`, wins: d.wins })));

Qué esperar.

=== whereToPlay: el segmento EXCLUIDO, ¿de verdad pierde? ===

segment: exactSkuShoppers | productWeightedScore: 5.3 | bestRival: genericMegastore (8.45) | fitsSegment: false | margin: -3.15

┌─────────┬──────────────────┬────────┬─────────┬──────────────────────┬───────┐
│ (index) │    dimension     │ weight │ product │      bestRival       │ wins  │
├─────────┼──────────────────┼────────┼─────────┼──────────────────────┼───────┤
│    0    │ 'catalogBreadth' │  0.1   │    6    │ 'genericMegastore:9' │ false │
│    1    │     'price'      │  0.35  │    5    │ 'genericMegastore:8' │ false │
│    2    │ 'deliverySpeed'  │  0.35  │    5    │ 'genericMegastore:9' │ false │
│    3    │  'convenience'   │  0.2   │    6    │ 'genericMegastore:8' │ false │
└─────────┴──────────────────┴────────┴─────────┴──────────────────────┴───────┘

La capa whereToPlay del one-pager queda así confirmada en las dos direcciones que importan: gana donde eligió jugar (margen +1.65), y pierde —sin ambigüedad, sin ganar una sola dimensión— donde decidió no jugar (margen −3.15). Esa asimetría —una victoria angosta y calculada contra una derrota total y sin apelación— es exactamente la huella de un "dónde jugar" bien elegido, no una casualidad de estos números.

Profundización: por qué esta capa no repite el módulo 3, lo cita

Fíjate en que esta lección no volvió a explicar qué es un beachhead, ni por qué un job-to-be-done define mejor un segmento que la demografía, ni cómo se construye un positioning statement con las cinco piezas de Dunford — todo eso ya lo aprendiste, a fondo, en las seis lecciones del módulo 3. Lo que esta lección hace es distinto: cita el resultado ya verificado de ese módulo, en el lugar exacto que le corresponde dentro del documento más grande. Esa es la diferencia entre un one-pager real y una recopilación de resúmenes — un resumen reexplica; una capa de one-pager reutiliza el trabajo ya hecho, sin reescribirlo, y agrega solo lo que hace falta para conectarlo con las capas vecinas.

Este patrón se repite en cada una de las lecciones que siguen: la lección 4 no vuelve a explicar qué es la paridad ni el mapa competitivo, corre differentiationMap y competitiveMap sobre los mismos datos del módulo 4 y 5. La lección 5 no vuelve a explicar los cinco tipos de moat, corre moatScore sobre el inventario del módulo 6. Cada capa del one-pager es una cita verificada, no una relectura.

Errores comunes

Redefinir el segmento "un poco distinto" al armar el one-pager. Qué pasa: alguien, al construir esta capa, ajusta ligeramente los pesos de explorers o cambia una de las alternativas —"para que se vea mejor en el documento final"—, sin darse cuenta de que ahora el one-pager ya no describe la misma estrategia que el resto de la guía verificó. Por qué pasa: el one-pager se siente como una oportunidad de "pulir" el resultado final, y un pequeño ajuste de números parece inofensivo comparado con reescribir toda la lógica. Cómo detectarlo: compara los datos de esta capa, campo por campo, contra el proyecto del módulo 3 (08-project-mercados-target-and-positioning.md) — si algo no coincide exactamente, alguien "mejoró" los datos sin correr de nuevo la verificación completa. Cómo corregirlo: esta capa se copia verbatim, sin excepciones. Si el segmento realmente necesita cambiar, ese cambio pertenece al módulo 3, no a este one-pager, y debería propagarse hacia atrás, no hacerse solo aquí.

Mostrar solo el segmento elegido, sin el excluido, "para no complicar el documento". Qué pasa: el one-pager final solo incluye la tabla de explorers ganando, y omite la verificación de que exactSkuShoppers de verdad pierde — el mismo error que el módulo 3 ya advirtió a nivel de proyecto, ahora repetido a nivel de one-pager. Por qué pasa: mostrar solo la victoria se siente más limpio y más persuasivo que mostrar también la comparación completa. Cómo detectarlo: si tu one-pager no puede responder, con un número exacto, "¿por qué NO perseguimos también a los compradores de SKU exacto, si son un mercado más grande?", la capa está incompleta. Cómo corregirlo: incluye siempre las dos corridas, como en esta lección — la fuerza de "dónde jugamos" está tanto en dónde ganamos como en dónde, honestamente, no.

Tratar fitsSegment: true como el final de la conversación de estrategia. Qué pasa: al ver que Mercado gana el segmento elegido, el equipo considera cerrado el trabajo de "dónde jugar" y pasa directo a construir, sin preguntarse todavía qué tan defendible es esa victoria en el tiempo. Por qué pasa: un resultado positivo se siente como una conclusión, cuando en realidad es solo la primera de cuatro capas que el one-pager completo necesita. Cómo detectarlo: si tu equipo celebra el resultado de positionFit sin mencionar todavía la palabra "diferenciación" ni "moat", falta la mayor parte del one-pager. Cómo corregirlo: recuerda que positionFit mide una fotografía de hoy — gana Mercado ahora, con los scores actuales. Las lecciones 4 y 5 completan la pregunta de si esa ventaja es real y si es defendible en el tiempo.

Ejercicios

Ejercicio 1 — Recalcula el margen con un rival más fuerte. Si localShop mejorara su sellerTrust de 9 a 10 (el máximo posible), ¿cambiaría el bestRival para el segmento explorers, y cambiaría el fitsSegment final? Calcula el nuevo productWeightedScore de localShop a mano antes de responder.

Ver solución

El productWeightedScore de localShop con sellerTrust: 10 sería: 0.4×6 + 0.3×10 + 0.1×2 + 0.1×4 + 0.05×3 + 0.05×3 = 2.4 + 3.0 + 0.2 + 0.4 + 0.15 + 0.15 = 6.3. Sigue por debajo de localShop original en curatedDiscovery (Mercado gana esa dimensión con más peso), así que localShop seguiría siendo el bestRival (ahora con 6.3 en vez de 6), y fitsSegment seguiría siendo true, aunque el margen de Mercado se reduciría de 1.65 a 1.35. El resultado no cambia de signo, pero sí de magnitud — una alerta temprana de que, si localShop sigue mejorando su confianza percibida, el margen de Mercado eventualmente podría revertirse.

Ejercicio 2 — Verifica un tercer segmento hipotético. Un bargainHunters (cazadores de ofertas) tiene weights: { curatedDiscovery: 0, sellerTrust: 0.1, catalogBreadth: 0.2, price: 0.5, deliverySpeed: 0.1, convenience: 0.1 }. Sin ejecutar nada, predice si fitsSegment sería true o false para Mercado, y qué tan grande esperarías que sea el margen comparado con exactSkuShoppers (−3.15).

Ver solución

fitsSegment sería false, y el margen sería negativo y de magnitud similar o mayor que exactSkuShoppers — este segmento pondera price todavía más fuerte (0.5 contra 0.35) y no le da ningún peso a curatedDiscovery, la única dimensión donde Mercado gana con claridad. Es, si acaso, un caso todavía más desfavorable para Mercado que exactSkuShoppers: comparte el mismo patrón (cero peso en la fortaleza de Mercado) pero concentra aún más peso en price, la dimensión donde genericMegastore domina sin competencia.

Ejercicio 3 — Conecta con la lección 4. El positioning statement de esta lección nombra curatedDiscovery como parte del beneficio clave, pero positionFit mide si Mercado gana hoy, no si esa ventaja es difícil de copiar. Escribe, en 2-3 frases, qué pregunta distinta va a responder la lección 4 sobre esta misma dimensión.

Ver solución

positionFit respondió "¿Mercado gana en curatedDiscovery frente a las alternativas de hoy, con los scores actuales?" — y la respuesta fue sí, con margen suficiente para ganar el segmento completo. La lección 4 va a preguntar algo distinto: de las seis dimensiones donde Mercado compite, ¿cuáles son diferenciación real —una ventaja de al menos 2 puntos sobre el mejor rival— y cuáles son solo paridad disfrazada de ventaja? Es la diferencia entre "ganamos hoy" (esta lección) y "esa victoria es sólida, no un empate técnico que parece ventaja" (la siguiente).

Resumen y siguiente paso

En esta lección llenaste la segunda capa del one-pager: whereToPlay, verificada con positionFit en las dos direcciones que importan — el segmento elegido gana con margen +1.65, y el segmento explícitamente excluido pierde con margen −3.15, sin ambigüedad. El positioning statement completo, con las cinco piezas de Dunford, queda fijado como parte de esta capa.

Antes de avanzar deberías tener claro: por qué whereToPlay tiene que existir antes que howToWin, y por qué verificar el segmento excluido es tan importante como verificar el elegido.

La lección 4 llena la tercera capa: cómo gana Mercado en el terreno que acaba de confirmar, con differentiationMap separando la diferenciación real de la paridad, y con el panorama competitivo completo del módulo 5 como contexto de cuánto tiempo va a durar esa ventaja.

Recursos