EcoVeridian v2.4.0

Wednesday, January 7, 2026

I Scrapped the Old Scoring System

Not because the data was wrong, but because I was measuring the wrong thing.

When I shipped v1.0.0, EcoVeridian gave companies an "ESG Score" (0-100) based on three categories: Environmental, Social, and Governance. It looked official. Had fancy breakdowns. Color-coded letter grades.

But here's the problem: ESG is too broad. A company could get an A+ on governance (strong board oversight, transparent financials) while simultaneously dumping toxic waste into rivers. The "ESG Score" averaged those together and gave you... what, exactly?

So I rebuilt the entire backend. v2.4.0 is live now, and it's completely different.


What Changed

Before (v1.0.0 - v2.0.0): The "ESG Score"

The old system worked like this:

  1. Search the web for sustainability reports
  2. Feed everything to our analysis engine
  3. Get back three scores (Environmental, Social, Governance)
  4. Average them into one "Eco-Score"
  5. Slap a letter grade on it (A+ to F)

The problem: This approach treated all three pillars equally. If a company had killer governance but terrible environmental practices, they'd still get a decent overall score. That's not useful.

I built this extension because I wanted to know if a company was wrecking the planet. Not whether their board meetings were well-documented.

Now (v2.4.0): The "GreenScore"

The new system is laser-focused on one thing: environmental risk.

Here's how it works:

  1. Search the web for environmental news (not generic sustainability marketing)
  2. Extract specific environmental events (lawsuits, spills, green initiatives, etc.)
  3. Score each event on 6 factors: impact, severity, credibility, recency, scope, confidence
  4. Run it through a log-compressed risk model to calculate a final GreenScore (0-100)
  5. Show the top 3 events driving that score

The difference: You're not getting a vague "sustainability rating" anymore. You're getting a risk assessment based on recent environmental events, weighted by source credibility and recency.


The New Scoring Engine (6-Factor Model)

This is the part I'm most proud of. The old system just counted "highlights" and "concerns" and averaged them. The new system is way more sophisticated.

Factor 1: Impact (-1 to +1)

How harmful or beneficial is this event?

  • -1.0 = Major environmental damage (e.g., oil spill, illegal logging)
  • 0.0 = Neutral
  • +1.0 = Major environmental benefit (e.g., carbon-negative operations, renewable energy transition)

The analysis engine evaluates each article and assigns an impact score.

Factor 2: Severity (0 to 1)

How serious is the issue?

  • 0.1 = Minor incident (small fine, temporary violation)
  • 0.5 = Moderate (ongoing pollution, regulatory investigation)
  • 1.0 = Severe (catastrophic spill, mass ecosystem damage)

This scales the magnitude of the impact.

Factor 3: Credibility (0 to 1)

How trustworthy is the source?

I built a multi-level credibility system:

Tier 1 (0.95-0.98): Government/regulatory sources

  • EPA, SEC, UN, Europa.eu
  • These are gold standard. If the EPA says you're polluting, you're polluting.

Tier 2 (0.90-0.92): Major news outlets & ESG orgs

  • Reuters, BBC, Bloomberg, CDP, SASB
  • Professional journalism with fact-checking standards

Tier 3 (0.75-0.88): Business news & sustainability media

  • Forbes, GreenBiz, ESG Today
  • Still credible, but more opinion/analysis mixed in

Tier 4 (0.60 default): Unknown sources

  • Random blogs, company press releases
  • Not inherently unreliable, but unverified

The smart part: For domains I don't recognize, I use automated source verification to assess credibility on the fly based on NewsGuard criteria (editorial standards, corrections policy, ownership transparency, etc.). Then I cache that result in Firestore so I never have to assess the same domain twice.

Factor 4: Recency (0 to 1)

How recent is the news?

Exponential decay with a 30-day half-life:

  • Today's news: 1.0
  • 30 days ago: 0.5
  • 60 days ago: 0.25
  • Older news decays further

Why this matters: A lawsuit from yesterday is more relevant than a sustainability pledge from 2 years ago.

Factor 5: Scope (0.5 to 1.0)

How widespread is the impact?

  • Global: 1.0 (affects multiple countries, global supply chains)
  • Regional: 0.7 (state/province level, regional ecosystems)
  • Local: 0.5 (single facility, localized pollution)

Factor 6: Confidence (0 to 1)

How certain is the model about its assessment?

If the article is vague or lacks details, confidence drops. Clear, specific incidents (e.g., "500,000 liters of crude oil spilled") get high confidence.


The Scoring Algorithm (Log Compression)

Here's where it gets technical. I could've just averaged the weighted impacts. But that would let many small positive actions wash out a single catastrophic event.

Example: If a company had 9 small green initiatives (+0.2 each) and 1 catastrophic oil spill (-1.0), a simple average would still give them a decent score. That's wrong.

So I use logarithmic compression to prevent any single event from skewing the score:

const compressedMagnitude = Math.log1p(Math.abs(event.impact) * event.severity);
const signedCompressedImpact = event.impact >= 0 ? compressedMagnitude : -compressedMagnitude;
const weightedImpact = signedCompressedImpact * (credibility * recency * scope * confidence);

What this does:

  • Compresses extreme values: An impact of -1.0 gets compressed to ~-0.69
  • Multiplies by all 6 factors: Recent, credible, high-scope events weigh more
  • Calculates mean risk: Average of all weighted impacts
  • Converts to 0-100 scale: GreenScore = 50 + (meanRisk * 70)

The result: Every event contributes, but no single event can hijack the score.

The UI now shows you the contribution percentage for each event. So if the score is 32 (high risk), you can see exactly which 3 events are driving that number.


The UI Overhaul

What's Gone

Removed:

  • ESG breakdown (Environmental/Social/Governance tabs)
  • Letter grades (A+ to F)
  • Generic "highlights" and "concerns"
  • Sources dropdown (was just a list of URLs)

Why I removed them: They were information overload. Nobody cares about 12 different highlights. They want to know: Is this company safe to support?

What's New

The GreenScore Circle

  • Big number (0-100) with a color-coded progress ring
  • Green (70+) = Low risk
  • Yellow (40-69) = Medium risk
  • Red (<40) = High risk

Risk Verdict

  • Simple badge: "Low risk" / "Medium risk" / "High risk"
  • Based on GreenScore thresholds

Score Summary

  • One paragraph explaining the score
  • Shows total events analyzed, harmful vs. beneficial split
  • Mentions which top events are driving the score

Key Sources (Top 3 Events)

  • Shows the 3 events with the highest contribution
  • Icons: ⚠️ for harmful, ✓ for beneficial (This is not the actual icons but I wasn't able to put the svg here)
  • Clickable links to the original article
  • Truncated titles (max 50 chars)

View Full Report Button

  • Opens the dashboard for detailed breakdown
  • Shows all events, contribution percentages, and full 6-factor analysis

Backend Changes (v2.4.0)

API Changes

Old response format:

{
  companyName: "Nike Inc.",
  ecoScore: 72,
  ecoGrade: "B",
  summary: "Nike has made significant progress...",
  breakdown: {
    environmental: { score: 68, highlights: [...], concerns: [...] },
    social: { score: 75, highlights: [...], concerns: [...] },
    governance: { score: 73, highlights: [...], concerns: [...] }
  },
  sources: ["url1", "url2", ...]
}

New response format:

{
  companyName: "Nike Inc.",
  environmentalRiskReport: {
    greenScore: 58,
    meanRisk: -0.124,
    riskLevel: "medium",
    verdict: "Medium risk",
    totalEvents: 7,
    harmfulEvents: 4,
    beneficialEvents: 3,
    seriousIssuesCount: 1,
    articles: [
      {
        title: "Nike faces lawsuit over carbon emissions claims",
        url: "https://...",
        eventScore: 32,
        impact: -0.6,
        severity: 0.7,
        credibility: 0.90,
        recency: 0.95,
        scope: 0.7,
        confidence: 0.85,
        contribution: 28,
        isHarmful: true
      },
      // ... more events
    ],
    scoreSummary: "Nike Inc. GreenScore = 58 (risk:-0.124). 7 events analyzed: 4 harmful, 3 beneficial. Score is driven primarily by the top 3 event(s) shown below; their combined contribution explains ~67% of total risk magnitude. Credibility and recency are incorporated, so regulator/NGO or very recent items weigh more."
  }
}

What changed:

  • Dropped ecoScore, ecoGrade, breakdown, sources
  • Added environmentalRiskReport with full event metrics
  • Includes contribution percentages for transparency

Cache Invalidation

The old cached data is incompatible with v2.4.0. So I added a cache format check:

const isValidFormat = cachedData.environmentalRiskReport?.greenScore !== undefined;

if (!isValidFormat) {
  console.log(`Invalidating old cache format for ${normalizedDomain}`);
  await cacheRef.delete();
}

Any user who analyzed a company on v2.0.0 will get a fresh analysis on v2.4.0. The old data is automatically deleted.


Tavily Search Changes

Before

const searchQueries = [
  `${companyName} sustainability report ESG environmental`,
  `${companyName} carbon footprint climate initiatives`,
  `${companyName} corporate social responsibility labor practices`
];

Search depth: Basic Max results: 3 per query

This was designed to find generic sustainability info. It worked, but it pulled a lot of marketing fluff.

Now

const searchQueries = [
  `${companyName} environmental impact pollution emissions`,
  `${companyName} sustainability green energy renewable`,
  `${companyName} climate change carbon footprint net zero`
];

Search depth: Advanced Max results: 5 per query

Why the change:

  • "Pollution emissions" finds lawsuits and violations
  • "Green energy renewable" finds actual initiatives (not just pledges)
  • Advanced depth gets deeper into regulatory filings and news archives

The old queries were too soft. The new ones are rigorous. If there's dirt, Tavily will find it.


What Broke (And How I Fixed It)

1. Firestore Cache Migration

The problem: Old cache entries used ecoScore. New format uses environmentalRiskReport.greenScore. If I didn't handle this, the extension would crash when loading old cache.

The fix:

const isValidFormat = cachedData.environmentalRiskReport?.greenScore !== undefined;

if (cacheAge < CACHE_TTL_MS && isValidFormat) {
  // Return cached data
} else if (!isValidFormat) {
  // Delete old format cache
  await cacheRef.delete();
}

2. Extension Type Mismatches

The problem: The extension was expecting data.ecoScore but the API now returns data.environmentalRiskReport.greenScore.

The fix: Updated all TypeScript interfaces in extension/src/api/analyzeCompany.ts:

export interface EnvironmentalRiskReport {
  greenScore: number;
  riskLevel: "low" | "medium" | "high";
  verdict: string;
  articles: ArticleMetrics[];
  scoreSummary: string;
}

export interface CompanyAnalysis {
  companyName: string;
  environmentalRiskReport: EnvironmentalRiskReport;
}

TypeScript caught every single reference to the old schema. Zero runtime errors.

3. UI Component Rewrites

The problem: The old SuccessState component had collapsible breakdown cards for E/S/G. The new design is completely different.

Replaced with:

  • Score circle (SVG progress ring)
  • Risk verdict badge
  • Score summary paragraph
  • Top 3 sources list
  • "View Full Report" CTA

The new UI is simpler.


What I'd Do Differently

I Should've Built GreenScore First

The ESG score was a distraction. I wasted time building breakdowns for Social and Governance when nobody asked for that. Users wanted to know: "Is this company trashing the environment?"

GreenScore answers that question. ESG doesn't.

If I could go back to v1.0.0, I'd skip the ESG approach entirely and build this from day one.


What's Next

  • Historical trend tracking (show if GreenScore is improving or worsening)
  • Sector benchmarking (compare companies to industry average)
  • Safari support (requires Manifest V3 conversion)
  • Dashboard deep-dives: Full event timeline, contribution breakdown, source analysis
  • Watchlists: Track specific companies and get alerts when their score changes

Closing Thoughts

v2.4.0 is the biggest update since launch. Since I rebuilt the entire scoring methodology from scratch.

The ESG score was technically correct, but strategically wrong. It measured too many things and diluted the signal.

GreenScore is laser-focused: environmental risk, backed by recent events, weighted by credibility.

If you're using EcoVeridian and a company's score suddenly dropped after this update, that's a good thing. It means the new system caught something the old one missed.

And if you see a score of 32 with a "High risk" verdict, don't buy from them. The data doesn't lie anymore.


EcoVeridian v2.4.0 is live now. Same extension, completely new brain.

Risith

Risith

Loading...