feat(notion): Finalize Competitive Radar v3.0 (Level 3 Relational Model)
- Extended import_relational_radar.py to include a 'Products' database. - Implemented full dual-way relations for Companies <-> Landmines, References, Products. - Updated documentation to reflect the 4-database architecture.
This commit is contained in:
@@ -72,11 +72,12 @@ Die App ist unter `/ca/` voll funktionsfähig und verfügt nun über eine "Groun
|
|||||||
### 📊 Relationaler Notion Import (Competitive Radar v2.0)
|
### 📊 Relationaler Notion Import (Competitive Radar v2.0)
|
||||||
Um die Analyse-Ergebnisse optimal nutzbar zu machen, wurde ein bidirektionaler Import-Prozess nach Notion implementiert (`import_relational_radar.py`).
|
Um die Analyse-Ergebnisse optimal nutzbar zu machen, wurde ein bidirektionaler Import-Prozess nach Notion implementiert (`import_relational_radar.py`).
|
||||||
|
|
||||||
* **Architektur:** Statt Textblöcken werden drei vernetzte Datenbanken erstellt:
|
* **Architektur:** Statt Textblöcken werden vier vernetzte Datenbanken erstellt:
|
||||||
1. **📦 Companies (Hub):** Stammdaten, USPs, Portfolio.
|
1. **📦 Companies (Hub):** Stammdaten, USPs, Portfolio-Summary.
|
||||||
2. **💣 Landmines (Satellite):** Einzelfragen und Angriffsvektoren, verknüpft mit der Company.
|
2. **💣 Landmines (Satellite):** Einzelfragen und Angriffsvektoren, verknüpft mit der Company.
|
||||||
3. **🏆 References (Satellite):** Konkrete Kundenprojekte, verknüpft mit der Company.
|
3. **🏆 References (Satellite):** Konkrete Kundenprojekte, verknüpft mit der Company.
|
||||||
* **Dual-Way Relations:** Dank `dual_property` Konfiguration sind die Verknüpfungen in Notion sofort in beide Richtungen navigierbar (z.B. sieht man auf der Company-Seite sofort alle zugehörigen Landmines).
|
4. **🤖 Products (Satellite):** Einzelne Produkte als Datensätze, ermöglicht marktweiten Vergleich (z.B. "Alle Reinigungsroboter").
|
||||||
|
* **Dual-Way Relations:** Dank `dual_property` Konfiguration sind die Verknüpfungen in Notion sofort in beide Richtungen navigierbar.
|
||||||
* **Daten-Qualität:** Durch die Map-Reduce Analyse und das gezielte Reference-Scraping werden nun echte Fakten statt KI-Halluzinationen importiert.
|
* **Daten-Qualität:** Durch die Map-Reduce Analyse und das gezielte Reference-Scraping werden nun echte Fakten statt KI-Halluzinationen importiert.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Die Schaltstelle für die hyper-personalisierte Ansprache.
|
|||||||
Automatisierte Überwachung der Marktbegleiter mit Fokus auf "Grounded Truth".
|
Automatisierte Überwachung der Marktbegleiter mit Fokus auf "Grounded Truth".
|
||||||
* **Funktion:** Kontinuierliches Scraping von Wettbewerber-Webseiten, gezielte Suche nach Referenzkunden und Case Studies.
|
* **Funktion:** Kontinuierliches Scraping von Wettbewerber-Webseiten, gezielte Suche nach Referenzkunden und Case Studies.
|
||||||
* **Kill-Argumente & Landmines:** Erstellung von strukturierten Battlecards und spezifischen "Landmine Questions" für den Sales-Außendienst.
|
* **Kill-Argumente & Landmines:** Erstellung von strukturierten Battlecards und spezifischen "Landmine Questions" für den Sales-Außendienst.
|
||||||
* **Relationaler Ansatz:** Trennung in drei verknüpfte Datenbanken (Firmen, Landmines, Referenzen) für maximale Filterbarkeit und Übersicht.
|
* **Relationaler Ansatz:** Trennung in vier verknüpfte Datenbanken (Firmen, Landmines, Referenzen, Produkte) für maximale Filterbarkeit und Übersicht.
|
||||||
|
|
||||||
### 3.5 Enrichment Factory & RevOps
|
### 3.5 Enrichment Factory & RevOps
|
||||||
Datenanreicherung der CRM-Accounts.
|
Datenanreicherung der CRM-Accounts.
|
||||||
@@ -93,6 +93,7 @@ Um die relationale Integrität zu wahren, sind folgende Datenbanken in Notion zw
|
|||||||
* **Messaging Matrix** $\leftrightarrow$ **Sector Master** (Welcher Schmerz gehört zu welcher Branche?)
|
* **Messaging Matrix** $\leftrightarrow$ **Sector Master** (Welcher Schmerz gehört zu welcher Branche?)
|
||||||
* **Competitive Radar (Companies)** $\leftrightarrow$ **Competitive Radar (Landmines)** (Welche Angriffsfragen gehören zu welchem Wettbewerber?)
|
* **Competitive Radar (Companies)** $\leftrightarrow$ **Competitive Radar (Landmines)** (Welche Angriffsfragen gehören zu welchem Wettbewerber?)
|
||||||
* **Competitive Radar (Companies)** $\leftrightarrow$ **Competitive Radar (References)** (Welche Kundenprojekte hat der Wettbewerber realisiert?)
|
* **Competitive Radar (Companies)** $\leftrightarrow$ **Competitive Radar (References)** (Welche Kundenprojekte hat der Wettbewerber realisiert?)
|
||||||
|
* **Competitive Radar (Companies)** $\leftrightarrow$ **Competitive Radar (Products)** (Welche Produkte hat der Wettbewerber im Portfolio?)
|
||||||
* **The Brain** $\leftrightarrow$ **Product Master** (Welches Support-Wissen gehört zu welcher Hardware?)
|
* **The Brain** $\leftrightarrow$ **Product Master** (Welches Support-Wissen gehört zu welcher Hardware?)
|
||||||
* **GTM Workspace** $\leftrightarrow$ **Product Master** (Welche Kampagne bewirbt welches Gerät?)
|
* **GTM Workspace** $\leftrightarrow$ **Product Master** (Welche Kampagne bewirbt welches Gerät?)
|
||||||
* **Feature-to-Value Translator** $\leftrightarrow$ **Product Master** (Welcher Nutzen gehört zu welchem Feature?)
|
* **Feature-to-Value Translator** $\leftrightarrow$ **Product Master** (Welcher Nutzen gehört zu welchem Feature?)
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import sys
|
|||||||
# Configuration
|
# Configuration
|
||||||
JSON_FILE = 'analysis_robo-planet.de.json'
|
JSON_FILE = 'analysis_robo-planet.de.json'
|
||||||
TOKEN_FILE = 'notion_token.txt'
|
TOKEN_FILE = 'notion_token.txt'
|
||||||
PARENT_PAGE_ID = "2e088f42-8544-8024-8289-deb383da3818"
|
PARENT_PAGE_ID = "2e088f42-8544-8024-8289-deb383da3818"
|
||||||
|
|
||||||
# Database Titles
|
# Database Titles
|
||||||
DB_TITLE_HUB = "📦 Competitive Radar (Companies)"
|
DB_TITLE_HUB = "📦 Competitive Radar (Companies)"
|
||||||
DB_TITLE_LANDMINES = "💣 Competitive Radar (Landmines & Intel)"
|
DB_TITLE_LANDMINES = "💣 Competitive Radar (Landmines & Intel)"
|
||||||
DB_TITLE_REFS = "🏆 Competitive Radar (References)"
|
DB_TITLE_REFS = "🏆 Competitive Radar (References)"
|
||||||
|
DB_TITLE_PRODUCTS = "🤖 Competitive Radar (Products)"
|
||||||
|
|
||||||
def load_json_data(filepath):
|
def load_json_data(filepath):
|
||||||
try:
|
try:
|
||||||
@@ -81,7 +82,7 @@ def main():
|
|||||||
token = load_notion_token(TOKEN_FILE)
|
token = load_notion_token(TOKEN_FILE)
|
||||||
data = load_json_data(JSON_FILE)
|
data = load_json_data(JSON_FILE)
|
||||||
|
|
||||||
print("🚀 Starting Relational Import...")
|
print("🚀 Starting Relational Import (Level 3 - Full Radar)...")
|
||||||
|
|
||||||
# --- STEP 1: Define & Create Competitors Hub DB ---
|
# --- STEP 1: Define & Create Competitors Hub DB ---
|
||||||
props_hub = {
|
props_hub = {
|
||||||
@@ -130,6 +131,19 @@ def main():
|
|||||||
}
|
}
|
||||||
refs_db_id = create_database(token, PARENT_PAGE_ID, DB_TITLE_REFS, props_refs)
|
refs_db_id = create_database(token, PARENT_PAGE_ID, DB_TITLE_REFS, props_refs)
|
||||||
|
|
||||||
|
# Products DB
|
||||||
|
props_products = {
|
||||||
|
"Product Name": {"title": {}},
|
||||||
|
"Purpose / Description": {"rich_text": {}},
|
||||||
|
"Related Competitor": {
|
||||||
|
"relation": {
|
||||||
|
"database_id": hub_db_id,
|
||||||
|
"dual_property": {"synced_property_name": "Related Products"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
products_db_id = create_database(token, PARENT_PAGE_ID, DB_TITLE_PRODUCTS, props_products)
|
||||||
|
|
||||||
# --- STEP 3: Import Competitors (and store IDs) ---
|
# --- STEP 3: Import Competitors (and store IDs) ---
|
||||||
competitor_map = {} # Maps Name -> Notion Page ID
|
competitor_map = {} # Maps Name -> Notion Page ID
|
||||||
|
|
||||||
@@ -156,10 +170,10 @@ def main():
|
|||||||
# Create Page
|
# Create Page
|
||||||
props = {
|
props = {
|
||||||
"Name": {"title": [{"text": {"content": c_name}}]},
|
"Name": {"title": [{"text": {"content": c_name}}]},
|
||||||
"Portfolio Summary": {"rich_text": [{"text": {"content": portfolio_text[:2000]}}]},
|
"Portfolio Summary": {"rich_text": [{"text": {"content": portfolio_text[:2000]}}]}, # Limit length
|
||||||
"USPs": {"rich_text": [{"text": {"content": usps[:2000]}}]},
|
"USPs": {"rich_text": [{"text": {"content": usps[:2000]}}]},
|
||||||
"Silver Bullet": {"rich_text": [{"text": {"content": silver_bullet[:2000]}}]},
|
"Silver Bullet": {"rich_text": [{"text": {"content": silver_bullet[:2000]}}]},
|
||||||
"Target Industries": {"multi_select": [{"name": i.replace(',', '')} for i in industries]},
|
"Target Industries": {"multi_select": [{"name": i.replace(',', '')} for i in industries]}
|
||||||
}
|
}
|
||||||
if c_url: props["Website"] = {"url": c_url}
|
if c_url: props["Website"] = {"url": c_url}
|
||||||
|
|
||||||
@@ -185,10 +199,8 @@ def main():
|
|||||||
create_page(token, landmines_db_id, props)
|
create_page(token, landmines_db_id, props)
|
||||||
|
|
||||||
# 2. Weaknesses
|
# 2. Weaknesses
|
||||||
# The JSON has "strengths_vs_weaknesses" combined. We'll import them as general Intel points.
|
|
||||||
for point in card.get('strengths_vs_weaknesses', []):
|
for point in card.get('strengths_vs_weaknesses', []):
|
||||||
# Try to guess type based on text, or just default to Weakness context from Battlecard
|
p_type = "Competitor Weakness"
|
||||||
p_type = "Competitor Weakness" # Assuming these are points for us to exploit
|
|
||||||
props = {
|
props = {
|
||||||
"Statement / Question": {"title": [{"text": {"content": point}}]},
|
"Statement / Question": {"title": [{"text": {"content": point}}]},
|
||||||
"Type": {"select": {"name": p_type}},
|
"Type": {"select": {"name": p_type}},
|
||||||
@@ -224,7 +236,30 @@ def main():
|
|||||||
count_refs += 1
|
count_refs += 1
|
||||||
|
|
||||||
print(f" - {count_refs} References imported.")
|
print(f" - {count_refs} References imported.")
|
||||||
print("\n✅ Relational Import Complete!")
|
|
||||||
|
# --- STEP 6: Import Products (Portfolio) ---
|
||||||
|
print("\nImporting Products...")
|
||||||
|
count_prods = 0
|
||||||
|
for analysis in data.get('analyses', []):
|
||||||
|
c_name = analysis.get('competitor', {}).get('name')
|
||||||
|
comp_page_id = competitor_map.get(c_name)
|
||||||
|
if not comp_page_id: continue
|
||||||
|
|
||||||
|
for prod in analysis.get('portfolio', []):
|
||||||
|
p_name = prod.get('product', 'Unknown Product')
|
||||||
|
p_purpose = prod.get('purpose', '')
|
||||||
|
|
||||||
|
props = {
|
||||||
|
"Product Name": {"title": [{"text": {"content": p_name}}]},
|
||||||
|
"Purpose / Description": {"rich_text": [{"text": {"content": p_purpose[:2000]}}]},
|
||||||
|
"Related Competitor": {"relation": [{"id": comp_page_id}]}
|
||||||
|
}
|
||||||
|
|
||||||
|
create_page(token, products_db_id, props)
|
||||||
|
count_prods += 1
|
||||||
|
|
||||||
|
print(f" - {count_prods} Products imported.")
|
||||||
|
print("\n✅ Relational Import Complete (Level 3)!")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
Reference in New Issue
Block a user