feat: SEO improvements and image optimization

- Enhanced SEO service with meta tags and structured data
- Updated sitemap service and robots.txt
- Optimized listing components for better SEO
- Compressed images (saved ~31MB total)
- Added .gitattributes to enforce LF line endings

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Timo Knuth 2026-02-03 19:48:30 +01:00
parent 0bbfc3f4fb
commit bf735ed60f
22 changed files with 4001 additions and 3923 deletions

View File

@ -26,7 +26,9 @@
"Bash(ls:*)", "Bash(ls:*)",
"WebFetch(domain:angular.dev)", "WebFetch(domain:angular.dev)",
"Bash(killall:*)", "Bash(killall:*)",
"Bash(echo:*)" "Bash(echo:*)",
"Bash(npm run build:*)",
"Bash(npx tsc:*)"
] ]
} }
} }

4
.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
* text=auto eol=lf
*.png binary
*.jpg binary
*.jpeg binary

View File

@ -18,7 +18,7 @@ interface SitemapIndexEntry {
@Injectable() @Injectable()
export class SitemapService { export class SitemapService {
private readonly baseUrl = 'https://biz-match.com'; private readonly baseUrl = 'https://www.bizmatch.net';
private readonly URLS_PER_SITEMAP = 10000; // Google best practice private readonly URLS_PER_SITEMAP = 10000; // Google best practice
constructor(@Inject(PG_CONNECTION) private readonly db: NodePgDatabase<typeof schema>) { } constructor(@Inject(PG_CONNECTION) private readonly db: NodePgDatabase<typeof schema>) { }

View File

@ -1,14 +1,17 @@
import { Routes } from '@angular/router'; import { Routes } from '@angular/router';
// Core components (eagerly loaded - needed for initial navigation)
import { LogoutComponent } from './components/logout/logout.component'; import { LogoutComponent } from './components/logout/logout.component';
import { NotFoundComponent } from './components/not-found/not-found.component'; import { NotFoundComponent } from './components/not-found/not-found.component';
import { TestSsrComponent } from './components/test-ssr/test-ssr.component'; import { TestSsrComponent } from './components/test-ssr/test-ssr.component';
import { EmailAuthorizedComponent } from './components/email-authorized/email-authorized.component'; import { EmailAuthorizedComponent } from './components/email-authorized/email-authorized.component';
import { EmailVerificationComponent } from './components/email-verification/email-verification.component'; import { EmailVerificationComponent } from './components/email-verification/email-verification.component';
import { LoginRegisterComponent } from './components/login-register/login-register.component'; import { LoginRegisterComponent } from './components/login-register/login-register.component';
// Guards
import { AuthGuard } from './guards/auth.guard'; import { AuthGuard } from './guards/auth.guard';
import { ListingCategoryGuard } from './guards/listing-category.guard'; import { ListingCategoryGuard } from './guards/listing-category.guard';
import { UserListComponent } from './pages/admin/user-list/user-list.component';
// Public pages (eagerly loaded - high traffic)
import { DetailsBusinessListingComponent } from './pages/details/details-business-listing/details-business-listing.component'; import { DetailsBusinessListingComponent } from './pages/details/details-business-listing/details-business-listing.component';
import { DetailsCommercialPropertyListingComponent } from './pages/details/details-commercial-property-listing/details-commercial-property-listing.component'; import { DetailsCommercialPropertyListingComponent } from './pages/details/details-commercial-property-listing/details-commercial-property-listing.component';
import { DetailsUserComponent } from './pages/details/details-user/details-user.component'; import { DetailsUserComponent } from './pages/details/details-user/details-user.component';
@ -16,16 +19,12 @@ import { HomeComponent } from './pages/home/home.component';
import { BrokerListingsComponent } from './pages/listings/broker-listings/broker-listings.component'; import { BrokerListingsComponent } from './pages/listings/broker-listings/broker-listings.component';
import { BusinessListingsComponent } from './pages/listings/business-listings/business-listings.component'; import { BusinessListingsComponent } from './pages/listings/business-listings/business-listings.component';
import { CommercialPropertyListingsComponent } from './pages/listings/commercial-property-listings/commercial-property-listings.component'; import { CommercialPropertyListingsComponent } from './pages/listings/commercial-property-listings/commercial-property-listings.component';
import { AccountComponent } from './pages/subscription/account/account.component';
import { EditBusinessListingComponent } from './pages/subscription/edit-business-listing/edit-business-listing.component';
import { EditCommercialPropertyListingComponent } from './pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component';
import { EmailUsComponent } from './pages/subscription/email-us/email-us.component';
import { FavoritesComponent } from './pages/subscription/favorites/favorites.component';
import { MyListingComponent } from './pages/subscription/my-listing/my-listing.component';
import { SuccessComponent } from './pages/success/success.component'; import { SuccessComponent } from './pages/success/success.component';
import { TermsOfUseComponent } from './pages/legal/terms-of-use.component'; import { TermsOfUseComponent } from './pages/legal/terms-of-use.component';
import { PrivacyStatementComponent } from './pages/legal/privacy-statement.component'; import { PrivacyStatementComponent } from './pages/legal/privacy-statement.component';
// Note: Account, Edit, Admin, Favorites, MyListing, and EmailUs components are now lazy-loaded below
export const routes: Routes = [ export const routes: Routes = [
{ {
path: 'test-ssr', path: 'test-ssr',
@ -99,58 +98,58 @@ export const routes: Routes = [
component: DetailsUserComponent, component: DetailsUserComponent,
}, },
// ######### // #########
// User edit // User edit (lazy-loaded)
{ {
path: 'account', path: 'account',
component: AccountComponent, loadComponent: () => import('./pages/subscription/account/account.component').then(m => m.AccountComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
{ {
path: 'account/:id', path: 'account/:id',
component: AccountComponent, loadComponent: () => import('./pages/subscription/account/account.component').then(m => m.AccountComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
// ######### // #########
// Create, Update Listings // Create, Update Listings (lazy-loaded)
{ {
path: 'editBusinessListing/:id', path: 'editBusinessListing/:id',
component: EditBusinessListingComponent, loadComponent: () => import('./pages/subscription/edit-business-listing/edit-business-listing.component').then(m => m.EditBusinessListingComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
{ {
path: 'createBusinessListing', path: 'createBusinessListing',
component: EditBusinessListingComponent, loadComponent: () => import('./pages/subscription/edit-business-listing/edit-business-listing.component').then(m => m.EditBusinessListingComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
{ {
path: 'editCommercialPropertyListing/:id', path: 'editCommercialPropertyListing/:id',
component: EditCommercialPropertyListingComponent, loadComponent: () => import('./pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component').then(m => m.EditCommercialPropertyListingComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
{ {
path: 'createCommercialPropertyListing', path: 'createCommercialPropertyListing',
component: EditCommercialPropertyListingComponent, loadComponent: () => import('./pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component').then(m => m.EditCommercialPropertyListingComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
// ######### // #########
// My Listings // My Listings (lazy-loaded)
{ {
path: 'myListings', path: 'myListings',
component: MyListingComponent, loadComponent: () => import('./pages/subscription/my-listing/my-listing.component').then(m => m.MyListingComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
// ######### // #########
// My Favorites // My Favorites (lazy-loaded)
{ {
path: 'myFavorites', path: 'myFavorites',
component: FavoritesComponent, loadComponent: () => import('./pages/subscription/favorites/favorites.component').then(m => m.FavoritesComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
// ######### // #########
// EMAil Us // Email Us (lazy-loaded)
{ {
path: 'emailUs', path: 'emailUs',
component: EmailUsComponent, loadComponent: () => import('./pages/subscription/email-us/email-us.component').then(m => m.EmailUsComponent),
// canActivate: [AuthGuard], // canActivate: [AuthGuard],
}, },
// ######### // #########
@ -174,9 +173,11 @@ export const routes: Routes = [
path: 'success', path: 'success',
component: SuccessComponent, component: SuccessComponent,
}, },
// #########
// Admin Pages (lazy-loaded)
{ {
path: 'admin/users', path: 'admin/users',
component: UserListComponent, loadComponent: () => import('./pages/admin/user-list/user-list.component').then(m => m.UserListComponent),
canActivate: [AuthGuard], canActivate: [AuthGuard],
}, },
// ######### // #########

View File

@ -10,7 +10,12 @@
<!-- <a routerLink="/login" class="text-primary-500 hover:underline">Login/Register</a> --> <!-- <a routerLink="/login" class="text-primary-500 hover:underline">Login/Register</a> -->
} }
</div> </div>
<button (click)="toggleMenu()" class="md:hidden text-neutral-600"> <button
(click)="toggleMenu()"
class="md:hidden text-neutral-600"
aria-label="Open navigation menu"
[attr.aria-expanded]="isMenuOpen"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16m-7 6h7"></path> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16m-7 6h7"></path>
</svg> </svg>
@ -26,7 +31,11 @@
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="text-white text-xl py-2">Log In</a> <a routerLink="/login" [queryParams]="{ mode: 'login' }" class="text-white text-xl py-2">Log In</a>
<a routerLink="/login" [queryParams]="{ mode: 'register' }" class="text-white text-xl py-2">Sign Up</a> <a routerLink="/login" [queryParams]="{ mode: 'register' }" class="text-white text-xl py-2">Sign Up</a>
} }
<button (click)="toggleMenu()" class="text-white mt-4"> <button
(click)="toggleMenu()"
class="text-white mt-4"
aria-label="Close navigation menu"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg> </svg>
@ -38,24 +47,41 @@
<!-- 1. px-4 für <main> (vorher px-2 sm:px-4) --> <!-- 1. px-4 für <main> (vorher px-2 sm:px-4) -->
<main class="flex flex-col items-center justify-center px-4 w-full flex-grow"> <main class="flex flex-col items-center justify-center px-4 w-full flex-grow">
<div <div
class="bg-cover-custom pb-12 md:py-20 flex flex-col w-full rounded-xl lg:rounded-2xl md:drop-shadow-custom-md lg:drop-shadow-custom-lg min-h-[calc(100vh_-_20rem)] lg:min-h-[calc(100vh_-_10rem)] max-sm:bg-contain max-sm:bg-bottom max-sm:bg-no-repeat max-sm:min-h-[60vh] max-sm:bg-primary-600" class="relative overflow-hidden pb-12 md:py-20 flex flex-col w-full rounded-xl lg:rounded-2xl md:drop-shadow-custom-md lg:drop-shadow-custom-lg min-h-[calc(100vh_-_20rem)] lg:min-h-[calc(100vh_-_10rem)] max-sm:min-h-[60vh] max-sm:bg-primary-600"
> >
<div class="flex justify-center w-full"> <!-- Optimized Background Image -->
<picture class="absolute inset-0 w-full h-full z-0 pointer-events-none">
<source srcset="/assets/images/flags_bg.avif" type="image/avif">
<img
width="2500"
height="1285"
fetchpriority="high"
loading="eager"
src="/assets/images/flags_bg.jpg"
alt=""
class="w-full h-full object-cover"
>
</picture>
<!-- Gradient Overlay -->
<div class="absolute inset-0 bg-gradient-to-b from-black/35 via-black/15 to-transparent z-0 pointer-events-none"></div>
<div class="flex justify-center w-full relative z-10">
<!-- 3. Für Mobile: m-2 statt max-w-xs; ab sm: wieder max-width und kein Margin --> <!-- 3. Für Mobile: m-2 statt max-w-xs; ab sm: wieder max-width und kein Margin -->
<div class="w-full m-2 sm:m-0 sm:max-w-md md:max-w-xl lg:max-w-2xl xl:max-w-3xl"> <div class="w-full m-2 sm:m-0 sm:max-w-md md:max-w-xl lg:max-w-2xl xl:max-w-3xl">
<!-- Hero-Container --> <!-- Hero-Container -->
<section class="relative"> <section class="relative">
<!-- Dein Hintergrundbild liegt hier per CSS oder absolutem <img> --> <!-- Dein Hintergrundbild liegt hier per CSS oder absolutem <img> -->
<!-- 1) Overlay: sorgt für Kontrast auf hellem Himmel --> <!-- 1) Overlay: sorgt für Kontrast auf hellem Himmel (Previous overlay removed, using new global overlay) -->
<div aria-hidden="true" class="pointer-events-none absolute inset-0"></div> <!-- <div aria-hidden="true" class="pointer-events-none absolute inset-0"></div> -->
<!-- 2) Textblock --> <!-- 2) Textblock -->
<div class="relative z-10 mx-auto max-w-4xl px-6 sm:px-6 py-4 sm:py-16 text-center text-white"> <div class="relative z-10 mx-auto max-w-4xl px-6 sm:px-6 py-4 sm:py-16 text-center text-white">
<h1 class="text-[1.55rem] sm:text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight leading-tight drop-shadow-[0_2px_6px_rgba(0,0,0,0.55)]">Buy & Sell Businesses and Commercial Properties</h1> <h1 class="text-[1.55rem] sm:text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight leading-tight drop-shadow-[0_2px_6px_rgba(0,0,0,0.55)]">Buy & Sell Businesses and Commercial Properties</h1>
<p class="mt-3 sm:mt-4 text-base sm:text-lg md:text-xl lg:text-2xl font-medium text-white/90 drop-shadow-[0_1.5px_4px_rgba(0,0,0,0.6)]"> <p class="mt-3 sm:mt-4 text-base sm:text-lg md:text-xl lg:text-2xl font-medium text-white/90 drop-shadow-[0_1.5px_4px_rgba(0,0,0,0.6)]">
Find profitable businesses for sale, commercial real estate, and franchise opportunities across the United States Buy profitable businesses for sale or sell your business to qualified buyers. Browse commercial real estate and franchise opportunities across the United States.
</p> </p>
</div> </div>
</section> </section>
@ -63,55 +89,66 @@
<div class="search-form-container bg-white bg-opacity-80 pb-4 md:pb-6 pt-2 px-3 sm:px-4 md:px-6 rounded-lg shadow-lg w-full" [ngClass]="{ 'pt-6': aiSearch }"> <div class="search-form-container bg-white bg-opacity-80 pb-4 md:pb-6 pt-2 px-3 sm:px-4 md:px-6 rounded-lg shadow-lg w-full" [ngClass]="{ 'pt-6': aiSearch }">
@if(!aiSearch){ @if(!aiSearch){
<div class="text-sm lg:text-base mb-1 text-center text-neutral-500 border-neutral-200 dark:text-neutral-400 dark:border-neutral-700 flex justify-between"> <div class="text-sm lg:text-base mb-1 text-center text-neutral-500 border-neutral-200 dark:text-neutral-400 dark:border-neutral-700 flex justify-between">
<ul class="flex flex-wrap -mb-px w-full"> <ul class="flex flex-wrap -mb-px w-full" role="tablist">
<li class="w-[33%]"> <li class="w-[33%]" role="presentation">
<a <button
type="button"
role="tab"
[attr.aria-selected]="activeTabAction === 'business'"
(click)="changeTab('business')" (click)="changeTab('business')"
[ngClass]=" [ngClass]="
activeTabAction === 'business' activeTabAction === 'business'
? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500'] ? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500']
: ['border-transparent', 'hover:text-neutral-600', 'hover:border-neutral-300', 'dark:hover:text-neutral-300'] : ['border-transparent', 'hover:text-neutral-600', 'hover:border-neutral-300', 'dark:hover:text-neutral-300']
" "
class="tab-link hover:cursor-pointer inline-flex items-center justify-center px-1 py-2 md:p-4 border-b-2 rounded-t-lg" class="tab-link w-full hover:cursor-pointer inline-flex items-center justify-center px-3 py-3 md:p-4 border-b-2 rounded-t-lg bg-transparent"
> >
<img src="/assets/images/business_logo.png" alt="Search businesses for sale" class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain" width="28" height="28" /> <img src="/assets/images/business_logo.png" alt="" aria-hidden="true" class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain" width="28" height="28" />
<span>Businesses</span> <span>Businesses</span>
</a> </button>
</li> </li>
@if ((numberOfCommercial$ | async) > 0) { @if ((numberOfCommercial$ | async) > 0) {
<li class="w-[33%]"> <li class="w-[33%]" role="presentation">
<a <button
type="button"
role="tab"
[attr.aria-selected]="activeTabAction === 'commercialProperty'"
(click)="changeTab('commercialProperty')" (click)="changeTab('commercialProperty')"
[ngClass]=" [ngClass]="
activeTabAction === 'commercialProperty' activeTabAction === 'commercialProperty'
? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500'] ? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500']
: ['border-transparent', 'hover:text-neutral-600', 'hover:border-neutral-300', 'dark:hover:text-neutral-300'] : ['border-transparent', 'hover:text-neutral-600', 'hover:border-neutral-300', 'dark:hover:text-neutral-300']
" "
class="tab-link hover:cursor-pointer inline-flex items-center justify-center px-1 py-2 md:p-4 border-b-2 rounded-t-lg" class="tab-link w-full hover:cursor-pointer inline-flex items-center justify-center px-3 py-3 md:p-4 border-b-2 rounded-t-lg bg-transparent"
> >
<img src="/assets/images/properties_logo.png" alt="Search commercial properties for sale" class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain" width="28" height="28" /> <img src="/assets/images/properties_logo.png" alt="" aria-hidden="true" class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain" width="28" height="28" />
<span>Properties</span> <span>Properties</span>
</a> </button>
</li> </li>
} }
<li class="w-[33%]"> <li class="w-[33%]" role="presentation">
<a <button
type="button"
role="tab"
[attr.aria-selected]="activeTabAction === 'broker'"
(click)="changeTab('broker')" (click)="changeTab('broker')"
[ngClass]=" [ngClass]="
activeTabAction === 'broker' activeTabAction === 'broker'
? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500'] ? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500']
: ['border-transparent', 'hover:text-neutral-600', 'hover:border-neutral-300', 'dark:hover:text-neutral-300'] : ['border-transparent', 'hover:text-neutral-600', 'hover:border-neutral-300', 'dark:hover:text-neutral-300']
" "
class="tab-link hover:cursor-pointer inline-flex items-center justify-center px-1 py-2 md:p-4 border-b-2 rounded-t-lg" class="tab-link w-full hover:cursor-pointer inline-flex items-center justify-center px-3 py-3 md:p-4 border-b-2 rounded-t-lg bg-transparent"
> >
<img <img
src="/assets/images/icon_professionals.png" src="/assets/images/icon_professionals.png"
alt="Search business professionals and brokers" alt=""
class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain bg-transparent" aria-hidden="true"
class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain"
style="mix-blend-mode: darken" style="mix-blend-mode: darken"
width="28" height="28"
/> />
<span>Professionals</span> <span>Professionals</span>
</a> </button>
</li> </li>
</ul> </ul>
</div> </div>
@ -119,7 +156,11 @@
<div class="w-full max-w-3xl mx-auto bg-white rounded-lg flex flex-col md:flex-row md:border md:border-neutral-300"> <div class="w-full max-w-3xl mx-auto bg-white rounded-lg flex flex-col md:flex-row md:border md:border-neutral-300">
<div class="md:flex-none md:w-48 flex-1 md:border-r border-neutral-300 overflow-hidden mb-2 md:mb-0"> <div class="md:flex-none md:w-48 flex-1 md:border-r border-neutral-300 overflow-hidden mb-2 md:mb-0">
<div class="relative max-sm:border border-neutral-300 rounded-md"> <div class="relative max-sm:border border-neutral-300 rounded-md">
<label for="type-filter" class="sr-only">Filter by type</label>
<select <select
id="type-filter"
aria-label="Filter by type"
class="appearance-none bg-transparent w-full py-4 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none min-h-[52px]" class="appearance-none bg-transparent w-full py-4 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none min-h-[52px]"
[ngModel]="criteria.types" [ngModel]="criteria.types"
(ngModelChange)="onTypesChange($event)" (ngModelChange)="onTypesChange($event)"
@ -138,6 +179,7 @@
<div class="md:flex-auto md:w-36 flex-grow md:border-r border-neutral-300 mb-2 md:mb-0"> <div class="md:flex-auto md:w-36 flex-grow md:border-r border-neutral-300 mb-2 md:mb-0">
<div class="relative max-sm:border border-neutral-300 rounded-md"> <div class="relative max-sm:border border-neutral-300 rounded-md">
<label for="location-search" class="sr-only">Search by city or state</label>
<ng-select <ng-select
class="custom md:border-none rounded-md md:rounded-none" class="custom md:border-none rounded-md md:rounded-none"
[multiple]="false" [multiple]="false"
@ -151,6 +193,8 @@
(ngModelChange)="setCityOrState($event)" (ngModelChange)="setCityOrState($event)"
placeholder="Enter City or State ..." placeholder="Enter City or State ..."
groupBy="type" groupBy="type"
labelForId="location-search"
aria-label="Search by city or state"
> >
@for (city of cities$ | async; track city.id) { @let state = city.type==='city'?city.content.state:''; @let separator = city.type==='city'?' - ':''; @for (city of cities$ | async; track city.id) { @let state = city.type==='city'?city.content.state:''; @let separator = city.type==='city'?' - ':'';
<ng-option [value]="city">{{ city.content.name }}{{ separator }}{{ state }}</ng-option> <ng-option [value]="city">{{ city.content.name }}{{ separator }}{{ state }}</ng-option>
@ -161,7 +205,10 @@
@if (criteria.radius && !aiSearch){ @if (criteria.radius && !aiSearch){
<div class="md:flex-none md:w-36 flex-1 md:border-r border-neutral-300 mb-2 md:mb-0"> <div class="md:flex-none md:w-36 flex-1 md:border-r border-neutral-300 mb-2 md:mb-0">
<div class="relative max-sm:border border-neutral-300 rounded-md"> <div class="relative max-sm:border border-neutral-300 rounded-md">
<label for="radius-filter" class="sr-only">Filter by radius</label>
<select <select
id="radius-filter"
aria-label="Filter by radius"
class="appearance-none bg-transparent w-full py-4 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none min-h-[52px]" class="appearance-none bg-transparent w-full py-4 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none min-h-[52px]"
(ngModelChange)="onRadiusChange($event)" (ngModelChange)="onRadiusChange($event)"
[ngModel]="criteria.radius" [ngModel]="criteria.radius"
@ -180,13 +227,13 @@
} }
<div class="bg-primary-500 hover:bg-primary-600 max-sm:rounded-md search-button"> <div class="bg-primary-500 hover:bg-primary-600 max-sm:rounded-md search-button">
@if( numberOfResults$){ @if( numberOfResults$){
<button class="w-full h-full text-white font-bold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[52px] flex items-center justify-center gap-2" (click)="search()"> <button aria-label="Search listings" class="w-full h-full text-white font-bold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[52px] flex items-center justify-center gap-2" (click)="search()">
<i class="fas fa-search"></i> <i class="fas fa-search" aria-hidden="true"></i>
<span>Search {{ numberOfResults$ | async }}</span> <span>Search {{ numberOfResults$ | async }}</span>
</button> </button>
}@else { }@else {
<button class="w-full h-full text-white font-bold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[52px] flex items-center justify-center gap-2" (click)="search()"> <button aria-label="Search listings" class="w-full h-full text-white font-bold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[52px] flex items-center justify-center gap-2" (click)="search()">
<i class="fas fa-search"></i> <i class="fas fa-search" aria-hidden="true"></i>
<span>Search</span> <span>Search</span>
</button> </button>
} }

View File

@ -1,36 +1,4 @@
.bg-cover-custom {
position: relative;
// Prioritize AVIF format (69KB) over JPG (26MB)
background-image: url('/assets/images/flags_bg.avif');
background-size: cover;
background-position: center;
border-radius: 20px;
// Fallback for browsers that don't support AVIF
@supports not (background-image: url('/assets/images/flags_bg.avif')) {
background-image: url('/assets/images/flags_bg.jpg');
}
// Add gradient overlay for better text contrast
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.35) 0%, rgba(0, 0, 0, 0.15) 40%, rgba(0, 0, 0, 0.05) 70%, rgba(0, 0, 0, 0) 100%);
border-radius: 20px;
pointer-events: none;
z-index: 1;
}
// Ensure content stays above overlay
> * {
position: relative;
z-index: 2;
}
}
select:not([size]) { select:not([size]) {
background-image: unset; background-image: unset;
} }
@ -269,3 +237,16 @@ header {
} }
} }
} }
// Screen reader only - visually hidden but accessible
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select'; import { NgSelectModule } from '@ng-select/ng-select';
@ -27,6 +27,7 @@ import { map2User } from '../../utils/utils';
imports: [CommonModule, FormsModule, RouterModule, NgSelectModule, FaqComponent], imports: [CommonModule, FormsModule, RouterModule, NgSelectModule, FaqComponent],
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrl: './home.component.scss', styleUrl: './home.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class HomeComponent { export class HomeComponent {
placeholders: string[] = ['Property close to Houston less than 10M', 'Franchise business in Austin price less than 500K']; placeholders: string[] = ['Property close to Houston less than 10M', 'Franchise business in Austin price less than 500K'];
@ -125,19 +126,15 @@ export class HomeComponent {
// Set SEO meta tags for home page // Set SEO meta tags for home page
this.seoService.updateMetaTags({ this.seoService.updateMetaTags({
title: 'BizMatch - Buy & Sell Businesses and Commercial Properties', title: 'BizMatch - Buy & Sell Businesses and Commercial Properties',
description: 'Find profitable businesses for sale, commercial real estate, and franchise opportunities across the United States. Browse thousands of listings from verified sellers and brokers.', description: 'Find profitable businesses for sale, commercial real estate, and franchise opportunities. Browse thousands of verified listings across the US.',
keywords: 'business for sale, businesses for sale, buy business, sell business, commercial property, commercial real estate, franchise opportunities, business broker, business marketplace', keywords: 'business for sale, businesses for sale, buy business, sell business, commercial property, commercial real estate, franchise opportunities, business broker, business marketplace',
type: 'website' type: 'website'
}); });
// Add Organization schema for brand identity and FAQ schema for AEO // Add Organization schema for brand identity
// NOTE: FAQ schema removed because FAQ section is hidden (violates Google's visible content requirement)
// FAQ content is preserved in component for future use when FAQ section is made visible
const organizationSchema = this.seoService.generateOrganizationSchema(); const organizationSchema = this.seoService.generateOrganizationSchema();
const faqSchema = this.seoService.generateFAQPageSchema(
this.faqItems.map(item => ({
question: item.question,
answer: item.answer
}))
);
// Add HowTo schema for buying a business // Add HowTo schema for buying a business
const howToSchema = this.seoService.generateHowToSchema({ const howToSchema = this.seoService.generateHowToSchema({
@ -175,7 +172,8 @@ export class HomeComponent {
// Add SearchBox schema for Sitelinks Search // Add SearchBox schema for Sitelinks Search
const searchBoxSchema = this.seoService.generateSearchBoxSchema(); const searchBoxSchema = this.seoService.generateSearchBoxSchema();
this.seoService.injectMultipleSchemas([organizationSchema, faqSchema, howToSchema, searchBoxSchema]); // Inject schemas (FAQ schema excluded - content not visible to users)
this.seoService.injectMultipleSchemas([organizationSchema, howToSchema, searchBoxSchema]);
// Clear all filters and sort options on initial load // Clear all filters and sort options on initial load
this.filterStateService.resetCriteria('businessListings'); this.filterStateService.resetCriteria('businessListings');

View File

@ -21,7 +21,7 @@
Policy. Policy.
</p> </p>
<p class="mb-4"> <p class="mb-4">
We may update our Privacy Policy from time to time. Our Privacy Policy was last updated in Febuary 2018 and is effective upon acceptance for new users. By continuing to use our websites or otherwise We may update our Privacy Policy from time to time. Our Privacy Policy was last updated in February 2018 and is effective upon acceptance for new users. By continuing to use our websites or otherwise
continuing to deal with us, you accept this Privacy Policy. continuing to deal with us, you accept this Privacy Policy.
</p> </p>
<p class="font-bold mb-4 mt-6">Collection of personal information</p> <p class="font-bold mb-4 mt-6">Collection of personal information</p>

View File

@ -17,6 +17,9 @@
<h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Professional Business Brokers & Advisors</h1> <h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Professional Business Brokers & Advisors</h1>
<p class="text-lg text-neutral-600">Connect with licensed business brokers, CPAs, attorneys, and other <p class="text-lg text-neutral-600">Connect with licensed business brokers, CPAs, attorneys, and other
professionals across the United States.</p> professionals across the United States.</p>
<div class="mt-4 text-base text-neutral-700 max-w-4xl">
<p>BizMatch connects business buyers and sellers with experienced professionals. Find qualified business brokers to help with your business sale or acquisition. Our platform features verified professionals including business brokers, M&A advisors, CPAs, and attorneys specializing in business transactions across the United States. Whether you're looking to buy or sell a business, our network of professionals can guide you through the process.</p>
</div>
</div> </div>
<!-- Mobile Filter Button --> <!-- Mobile Filter Button -->

View File

@ -1,5 +1,5 @@
import { CommonModule, NgOptimizedImage } from '@angular/common'; import { CommonModule, NgOptimizedImage } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { UntilDestroy } from '@ngneat/until-destroy'; import { UntilDestroy } from '@ngneat/until-destroy';
@ -29,6 +29,7 @@ import { assignProperties, resetUserListingCriteria, map2User } from '../../../u
imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, CustomerSubTypeComponent, BreadcrumbsComponent, SearchModalBrokerComponent], imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, CustomerSubTypeComponent, BreadcrumbsComponent, SearchModalBrokerComponent],
templateUrl: './broker-listings.component.html', templateUrl: './broker-listings.component.html',
styleUrls: ['./broker-listings.component.scss', '../../pages.scss'], styleUrls: ['./broker-listings.component.scss', '../../pages.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class BrokerListingsComponent implements OnInit, OnDestroy { export class BrokerListingsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();

View File

@ -17,6 +17,9 @@
<h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Businesses for Sale</h1> <h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Businesses for Sale</h1>
<p class="text-lg text-neutral-600">Discover profitable business opportunities across the United States. Browse <p class="text-lg text-neutral-600">Discover profitable business opportunities across the United States. Browse
verified listings from business owners and brokers.</p> verified listings from business owners and brokers.</p>
<div class="mt-4 text-base text-neutral-700 max-w-4xl">
<p>BizMatch features thousands of businesses for sale across all industries and price ranges. Browse restaurants, retail stores, franchises, service businesses, e-commerce operations, and manufacturing companies. Each listing includes financial details, years established, location information, and seller contact details. Our marketplace connects business buyers with sellers and brokers nationwide, making it easy to find your next business opportunity.</p>
</div>
</div> </div>
<!-- Loading Skeleton --> <!-- Loading Skeleton -->

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { UntilDestroy } from '@ngneat/until-destroy'; import { UntilDestroy } from '@ngneat/until-destroy';
@ -31,6 +31,7 @@ import { map2User } from '../../../utils/utils';
imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, SearchModalComponent, LazyLoadImageDirective, BreadcrumbsComponent], imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, SearchModalComponent, LazyLoadImageDirective, BreadcrumbsComponent],
templateUrl: './business-listings.component.html', templateUrl: './business-listings.component.html',
styleUrls: ['./business-listings.component.scss', '../../pages.scss'], styleUrls: ['./business-listings.component.scss', '../../pages.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class BusinessListingsComponent implements OnInit, OnDestroy { export class BusinessListingsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
@ -86,8 +87,8 @@ export class BusinessListingsComponent implements OnInit, OnDestroy {
// Set SEO meta tags for business listings page // Set SEO meta tags for business listings page
this.seoService.updateMetaTags({ this.seoService.updateMetaTags({
title: 'Businesses for Sale - Find Profitable Business Opportunities | BizMatch', title: 'Businesses for Sale - Profitable Opportunities | BizMatch',
description: 'Browse thousands of businesses for sale across the United States. Find restaurants, franchises, retail stores, and more. Verified listings from business owners and brokers.', description: 'Browse thousands of businesses for sale. Find restaurants, franchises, retail stores, and more. Verified listings from owners and brokers.',
keywords: 'businesses for sale, buy a business, business opportunities, franchise for sale, restaurant for sale, retail business for sale, business broker listings', keywords: 'businesses for sale, buy a business, business opportunities, franchise for sale, restaurant for sale, retail business for sale, business broker listings',
type: 'website' type: 'website'
}); });

View File

@ -16,6 +16,9 @@
<div class="mb-6"> <div class="mb-6">
<h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Commercial Properties for Sale</h1> <h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Commercial Properties for Sale</h1>
<p class="text-lg text-neutral-600">Find office buildings, retail spaces, warehouses, and industrial properties across the United States. Investment opportunities from verified sellers and commercial real estate brokers.</p> <p class="text-lg text-neutral-600">Find office buildings, retail spaces, warehouses, and industrial properties across the United States. Investment opportunities from verified sellers and commercial real estate brokers.</p>
<div class="mt-4 text-base text-neutral-700 max-w-4xl">
<p>BizMatch showcases commercial real estate listings including office buildings, retail spaces, warehouses, and industrial properties for sale or lease. Browse investment properties across the United States with detailed information on square footage, zoning, pricing, and location. Our platform connects property buyers and investors with sellers and commercial real estate brokers. Find shopping centers, medical buildings, land parcels, and mixed-use developments in your target market.</p>
</div>
</div> </div>
@if(listings?.length > 0) { @if(listings?.length > 0) {

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { UntilDestroy } from '@ngneat/until-destroy'; import { UntilDestroy } from '@ngneat/until-destroy';
@ -30,6 +30,7 @@ import { map2User } from '../../../utils/utils';
imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, SearchModalCommercialComponent, LazyLoadImageDirective, BreadcrumbsComponent], imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, SearchModalCommercialComponent, LazyLoadImageDirective, BreadcrumbsComponent],
templateUrl: './commercial-property-listings.component.html', templateUrl: './commercial-property-listings.component.html',
styleUrls: ['./commercial-property-listings.component.scss', '../../pages.scss'], styleUrls: ['./commercial-property-listings.component.scss', '../../pages.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class CommercialPropertyListingsComponent implements OnInit, OnDestroy { export class CommercialPropertyListingsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
@ -83,8 +84,8 @@ export class CommercialPropertyListingsComponent implements OnInit, OnDestroy {
// Set SEO meta tags for commercial property listings page // Set SEO meta tags for commercial property listings page
this.seoService.updateMetaTags({ this.seoService.updateMetaTags({
title: 'Commercial Properties for Sale - Office, Retail, Industrial Real Estate | BizMatch', title: 'Commercial Properties for Sale - Office, Retail | BizMatch',
description: 'Browse commercial real estate listings including office buildings, retail spaces, warehouses, and industrial properties. Investment opportunities from verified sellers and brokers across the United States.', description: 'Browse commercial real estate: office buildings, retail spaces, warehouses, and industrial properties. Verified investment opportunities.',
keywords: 'commercial property for sale, commercial real estate, office building for sale, retail space for sale, warehouse for sale, industrial property, investment property, commercial property listings', keywords: 'commercial property for sale, commercial real estate, office building for sale, retail space for sale, warehouse for sale, industrial property, investment property, commercial property listings',
type: 'website' type: 'website'
}); });

View File

@ -23,9 +23,9 @@ export class SeoService {
private platformId = inject(PLATFORM_ID); private platformId = inject(PLATFORM_ID);
private isBrowser = isPlatformBrowser(this.platformId); private isBrowser = isPlatformBrowser(this.platformId);
private readonly defaultImage = 'https://biz-match.com/assets/images/bizmatch-og-image.jpg'; private readonly defaultImage = 'https://www.bizmatch.net/assets/images/bizmatch-og-image.jpg';
private readonly siteName = 'BizMatch'; private readonly siteName = 'BizMatch';
private readonly baseUrl = 'https://biz-match.com'; private readonly baseUrl = 'https://www.bizmatch.net';
/** /**
* Get the base URL for SEO purposes * Get the base URL for SEO purposes
@ -418,6 +418,7 @@ export class SeoService {
/** /**
* Generate Organization schema for the company * Generate Organization schema for the company
* Enhanced for Knowledge Graph and entity verification
*/ */
generateOrganizationSchema(): object { generateOrganizationSchema(): object {
return { return {
@ -427,18 +428,47 @@ export class SeoService {
'url': this.baseUrl, 'url': this.baseUrl,
'logo': `${this.baseUrl}/assets/images/bizmatch-logo.png`, 'logo': `${this.baseUrl}/assets/images/bizmatch-logo.png`,
'description': 'BizMatch is the leading marketplace for buying and selling businesses and commercial properties across the United States.', 'description': 'BizMatch is the leading marketplace for buying and selling businesses and commercial properties across the United States.',
// Physical address for entity verification
'address': {
'@type': 'PostalAddress',
'streetAddress': '1001 Blucher Street',
'addressLocality': 'Corpus Christi',
'addressRegion': 'TX',
'postalCode': '78401',
'addressCountry': 'US'
},
// Contact information (E.164 format)
'telephone': '+1-800-840-6025',
'email': 'info@bizmatch.net',
// Social media and entity verification
'sameAs': [ 'sameAs': [
'https://www.facebook.com/bizmatch', 'https://www.facebook.com/bizmatch',
'https://www.linkedin.com/company/bizmatch', 'https://www.linkedin.com/company/bizmatch',
'https://twitter.com/bizmatch' 'https://twitter.com/bizmatch'
// Future: Add Wikidata, Crunchbase, Wikipedia when available
], ],
// Enhanced contact point
'contactPoint': { 'contactPoint': {
'@type': 'ContactPoint', '@type': 'ContactPoint',
'telephone': '+1-800-BIZ-MATCH', 'telephone': '+1-800-840-6025',
'contactType': 'Customer Service', 'contactType': 'Customer Service',
'areaServed': 'US', 'areaServed': 'US',
'availableLanguage': 'English' 'availableLanguage': 'English',
} 'email': 'info@bizmatch.net'
},
// Business details for Knowledge Graph
'foundingDate': '2020',
'knowsAbout': [
'Business Brokerage',
'Commercial Real Estate',
'Business Valuation',
'Franchise Opportunities'
]
}; };
} }

View File

@ -11,7 +11,7 @@ export interface SitemapUrl {
providedIn: 'root' providedIn: 'root'
}) })
export class SitemapService { export class SitemapService {
private readonly baseUrl = 'https://biz-match.com'; private readonly baseUrl = 'https://www.bizmatch.net';
/** /**
* Generate XML sitemap content * Generate XML sitemap content

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 MiB

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -1,6 +1,6 @@
// Build information, automatically generated by `the_build_script` :zwinkern: // Build information, automatically generated by `the_build_script` :zwinkern:
const build = { const build = {
timestamp: "GER: 06.01.2026 22:33 | TX: 01/06/2026 3:33 PM" timestamp: "GER: 03.02.2026 12:44 | TX: 02/03/2026 5:44 AM"
}; };
export default build; export default build;

View File

@ -1,6 +1,6 @@
# robots.txt for BizMatch - Business Marketplace # robots.txt for BizMatch - Business Marketplace
# https://biz-match.com # https://www.bizmatch.net
# Last updated: 2026-01-02 # Last updated: 2026-02-03
# =========================================== # ===========================================
# Default rules for all crawlers # Default rules for all crawlers
@ -37,6 +37,9 @@ Disallow: /emailUs
Disallow: /api/ Disallow: /api/
Disallow: /bizmatch/ Disallow: /bizmatch/
# Disallow Cloudflare internal paths (prevents 404 errors in crawl reports)
Disallow: /cdn-cgi/
# Disallow search result pages with parameters (to avoid duplicate content) # Disallow search result pages with parameters (to avoid duplicate content)
Disallow: /*?*sortBy= Disallow: /*?*sortBy=
Disallow: /*?*page= Disallow: /*?*page=
@ -127,14 +130,14 @@ Disallow: /
# Sitemap locations # Sitemap locations
# =========================================== # ===========================================
# Main sitemap index (dynamically generated, contains all sub-sitemaps) # Main sitemap index (dynamically generated, contains all sub-sitemaps)
Sitemap: https://biz-match.com/bizmatch/sitemap.xml Sitemap: https://www.bizmatch.net/bizmatch/sitemap.xml
# Individual sitemaps (auto-listed in sitemap index) # Individual sitemaps (auto-listed in sitemap index)
# - https://biz-match.com/bizmatch/sitemap/static.xml # - https://www.bizmatch.net/bizmatch/sitemap/static.xml
# - https://biz-match.com/bizmatch/sitemap/business-1.xml # - https://www.bizmatch.net/bizmatch/sitemap/business-1.xml
# - https://biz-match.com/bizmatch/sitemap/commercial-1.xml # - https://www.bizmatch.net/bizmatch/sitemap/commercial-1.xml
# =========================================== # ===========================================
# Host directive (for Yandex) # Host directive (for Yandex)
# =========================================== # ===========================================
Host: https://biz-match.com Host: https://www.bizmatch.net