EcoVeridian v2.4.0
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:
- Search the web for sustainability reports
- Feed everything to our analysis engine
- Get back three scores (Environmental, Social, Governance)
- Average them into one "Eco-Score"
- 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:
- Search the web for environmental news (not generic sustainability marketing)
- Extract specific environmental events (lawsuits, spills, green initiatives, etc.)
- Score each event on 6 factors: impact, severity, credibility, recency, scope, confidence
- Run it through a log-compressed risk model to calculate a final GreenScore (0-100)
- 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
environmentalRiskReportwith 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.
