SEO/AEO, Farb schema, breadcrumbs
This commit is contained in:
135
bizmatch/src/app/services/sitemap.service.ts
Normal file
135
bizmatch/src/app/services/sitemap.service.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
export interface SitemapUrl {
|
||||
loc: string;
|
||||
lastmod?: string;
|
||||
changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
|
||||
priority?: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SitemapService {
|
||||
private readonly baseUrl = 'https://biz-match.com';
|
||||
|
||||
/**
|
||||
* Generate XML sitemap content
|
||||
*/
|
||||
generateSitemap(urls: SitemapUrl[]): string {
|
||||
const urlElements = urls.map(url => this.generateUrlElement(url)).join('\n ');
|
||||
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
${urlElements}
|
||||
</urlset>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single URL element for the sitemap
|
||||
*/
|
||||
private generateUrlElement(url: SitemapUrl): string {
|
||||
let element = `<url>\n <loc>${url.loc}</loc>`;
|
||||
|
||||
if (url.lastmod) {
|
||||
element += `\n <lastmod>${url.lastmod}</lastmod>`;
|
||||
}
|
||||
|
||||
if (url.changefreq) {
|
||||
element += `\n <changefreq>${url.changefreq}</changefreq>`;
|
||||
}
|
||||
|
||||
if (url.priority !== undefined) {
|
||||
element += `\n <priority>${url.priority.toFixed(1)}</priority>`;
|
||||
}
|
||||
|
||||
element += '\n </url>';
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sitemap URLs for static pages
|
||||
*/
|
||||
getStaticPageUrls(): SitemapUrl[] {
|
||||
return [
|
||||
{
|
||||
loc: `${this.baseUrl}/`,
|
||||
changefreq: 'daily',
|
||||
priority: 1.0
|
||||
},
|
||||
{
|
||||
loc: `${this.baseUrl}/home`,
|
||||
changefreq: 'daily',
|
||||
priority: 1.0
|
||||
},
|
||||
{
|
||||
loc: `${this.baseUrl}/listings`,
|
||||
changefreq: 'daily',
|
||||
priority: 0.9
|
||||
},
|
||||
{
|
||||
loc: `${this.baseUrl}/listings-2`,
|
||||
changefreq: 'daily',
|
||||
priority: 0.8
|
||||
},
|
||||
{
|
||||
loc: `${this.baseUrl}/listings-3`,
|
||||
changefreq: 'daily',
|
||||
priority: 0.8
|
||||
},
|
||||
{
|
||||
loc: `${this.baseUrl}/listings-4`,
|
||||
changefreq: 'daily',
|
||||
priority: 0.8
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sitemap URLs for business listings
|
||||
*/
|
||||
generateBusinessListingUrls(listings: any[]): SitemapUrl[] {
|
||||
return listings.map(listing => ({
|
||||
loc: `${this.baseUrl}/details-business-listing/${listing.id}`,
|
||||
lastmod: this.formatDate(listing.updated || listing.created),
|
||||
changefreq: 'weekly' as const,
|
||||
priority: 0.8
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sitemap URLs for commercial property listings
|
||||
*/
|
||||
generateCommercialPropertyUrls(properties: any[]): SitemapUrl[] {
|
||||
return properties.map(property => ({
|
||||
loc: `${this.baseUrl}/details-commercial-property/${property.id}`,
|
||||
lastmod: this.formatDate(property.updated || property.created),
|
||||
changefreq: 'weekly' as const,
|
||||
priority: 0.8
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date to ISO 8601 format (YYYY-MM-DD)
|
||||
*/
|
||||
private formatDate(date: Date | string): string {
|
||||
const d = typeof date === 'string' ? new Date(date) : date;
|
||||
return d.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate complete sitemap with all URLs
|
||||
*/
|
||||
async generateCompleteSitemap(
|
||||
businessListings: any[],
|
||||
commercialProperties: any[]
|
||||
): Promise<string> {
|
||||
const allUrls = [
|
||||
...this.getStaticPageUrls(),
|
||||
...this.generateBusinessListingUrls(businessListings),
|
||||
...this.generateCommercialPropertyUrls(commercialProperties)
|
||||
];
|
||||
|
||||
return this.generateSitemap(allUrls);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user