How to Add Merchant Logos to Your Fintech App
Merchant logos make bank transactions instantly recognizable. Here's how to get high-quality logos and display them in your React or Next.js app.
Open any modern banking app — Revolut, Monzo, N26 — and you'll see merchant logos next to every transaction. It's a small detail that makes a huge difference in user experience. Without logos, your transaction list is a wall of text. With logos, users can scan and find transactions instantly.
Why Merchant Logos Matter
Research from neobanks shows that merchant logos in transaction feeds:
- Reduce support tickets — Users can identify transactions without calling support to ask "what's this charge?"
- Increase engagement — Visually rich feeds keep users in the app longer
- Build trust — A polished UI signals a professional, trustworthy product
- Speed up recognition — Humans process images 60,000x faster than text
Before & After: The Visual Impact
Here's what a transaction list looks like without vs. with merchant logos:
How to Get Merchant Logos
There are three common approaches to getting merchant logos:
Option 1: Favicon Scraping (Unreliable)
The simplest approach is to extract the merchant's domain and fetch its favicon. Services like Google's favicon API or DuckDuckGo's icon service can help:
// Google favicon API (low resolution, often blurry)
const faviconUrl = `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;
// Problems:
// 1. You need to know the domain (hard to extract from "AMZN MKTP US*2K1AB")
// 2. Many favicons are 16x16 or 32x32 — too small for mobile apps
// 3. Some merchants don't have favicons at all
// 4. Rate limits and reliability issuesOption 2: Manual Logo Database (Doesn't Scale)
Some teams maintain their own logo database. This works for the top 100 merchants but falls apart quickly: you need to handle different sizes, formats, dark/light mode variants, and keep up with rebrands. It's a full-time job.
Option 3: Transaction Enrichment API (Recommended)
The best approach is to use a transaction enrichment API that returns logos as part of the enrichment response. You get the merchant name, category, and logo in a single API call.
// Easy Enrichment returns logo_url with every response
const result = await fetch('https://api.easyenrichment.com/enrich', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
description: 'AMZN MKTP US*2K1AB0C9Z',
amount: 49.99,
}),
}).then(r => r.json());
console.log(result.logo_url);
// "https://logo.easyenrichment.com/amazon.com"
// High-res, CDN-cached, always availableImplementing Logos in React / Next.js
Here's a production-ready React component for displaying transaction logos with fallbacks:
import { useState } from 'react';
import Image from 'next/image';
interface MerchantLogoProps {
logoUrl?: string;
merchantName: string;
size?: number;
}
export function MerchantLogo({
logoUrl,
merchantName,
size = 40,
}: MerchantLogoProps) {
const [hasError, setHasError] = useState(false);
// Generate a consistent color from merchant name
const getColor = (name: string) => {
const colors = [
'bg-blue-500', 'bg-green-500', 'bg-purple-500',
'bg-orange-500', 'bg-pink-500', 'bg-indigo-500',
];
let hash = 0;
for (let i = 0; i < name.length; i++) {
hash = name.charCodeAt(i) + ((hash << 5) - hash);
}
return colors[Math.abs(hash) % colors.length];
};
if (!logoUrl || hasError) {
// Fallback: colored circle with initial
return (
<div
className={`${getColor(merchantName)} rounded-xl flex items-center
justify-center text-white font-bold`}
style={{ width: size, height: size, fontSize: size * 0.4 }}
>
{merchantName.charAt(0).toUpperCase()}
</div>
);
}
return (
<Image
src={logoUrl}
alt={merchantName}
width={size}
height={size}
className="rounded-xl object-contain bg-white"
onError={() => setHasError(true)}
/>
);
}Using the Component in a Transaction List
interface Transaction {
id: string;
merchant_name: string;
category: string;
amount: number;
date: string;
logo_url?: string;
}
function TransactionList({ transactions }: { transactions: Transaction[] }) {
return (
<div className="divide-y divide-zinc-800">
{transactions.map((txn) => (
<div key={txn.id} className="flex items-center gap-3 py-3">
<MerchantLogo
logoUrl={txn.logo_url}
merchantName={txn.merchant_name}
/>
<div className="flex-1 min-w-0">
<div className="font-medium text-white truncate">
{txn.merchant_name}
</div>
<div className="text-sm text-zinc-500">{txn.category}</div>
</div>
<div className="text-right">
<div className="font-medium text-white">
{`-$${txn.amount.toFixed(2)}`}
</div>
<div className="text-sm text-zinc-500">{txn.date}</div>
</div>
</div>
))}
</div>
);
}Performance Tips
- Use Next.js Image component: It handles lazy loading, responsive sizes, and format optimization automatically.
- Add logo URLs to next.config.js: Whitelist the logo CDN domain in
images.remotePatternsfor Next.js image optimization. - Store logo URLs in your database: Don't call the enrichment API on every page load. Store the logo URL when you first enrich the transaction.
- Always implement a fallback: Even the best logo service won't cover 100% of merchants. The colored-initial fallback keeps your UI consistent.
- Preload above-the-fold logos: Use
priorityprop on the first 5-10 logos to eliminate layout shift.
Next.js Configuration
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'logo.easyenrichment.com',
pathname: '/**',
},
],
},
};Get Merchant Logos with Easy Enrichment
Every API response includes a high-resolution merchant logo URL, along with the merchant name, category, and 15+ other fields. Start free with 500 requests/month.