""" SEO Module für Kasico Fursuit Shop Meta Tags, Structured Data, Sitemap Generation """ from django.utils.html import strip_tags from django.template.loader import render_to_string from django.contrib.sites.models import Site from django.urls import reverse from django.utils import timezone import json class SEOManager: """SEO Manager für Meta Tags und Structured Data""" def __init__(self, request=None): self.request = request self.site = Site.objects.get_current() self.base_url = f"https://{self.site.domain}" def get_product_meta_tags(self, product): """Meta Tags für Produkt-Seiten""" meta_tags = { 'title': f"{product.name} - Kasico Fursuit Shop", 'description': self._clean_description(product.description), 'keywords': f"fursuit, {product.fursuit_type}, {product.style}, custom fursuit, furry", 'og_title': product.name, 'og_description': self._clean_description(product.description), 'og_type': 'product', 'og_image': self._get_product_image_url(product), 'og_url': f"{self.base_url}{product.get_absolute_url()}", 'twitter_card': 'summary_large_image', 'twitter_title': product.name, 'twitter_description': self._clean_description(product.description), 'twitter_image': self._get_product_image_url(product), 'canonical_url': f"{self.base_url}{product.get_absolute_url()}", } # Preis-Informationen für E-Commerce if product.on_sale: meta_tags['price'] = str(product.sale_price) meta_tags['original_price'] = str(product.base_price) else: meta_tags['price'] = str(product.base_price) return meta_tags def get_category_meta_tags(self, category): """Meta Tags für Kategorie-Seiten""" meta_tags = { 'title': f"{category.name} Fursuits - Kasico Shop", 'description': f"Entdecke unsere {category.name} Fursuits. Handgefertigte, hochwertige Fursuits in verschiedenen Stilen und Größen.", 'keywords': f"{category.name}, fursuit, furry, custom fursuit", 'og_title': f"{category.name} Fursuits", 'og_description': f"Entdecke unsere {category.name} Fursuits bei Kasico", 'og_type': 'website', 'og_url': f"{self.base_url}{category.get_absolute_url()}", 'canonical_url': f"{self.base_url}{category.get_absolute_url()}", } return meta_tags def get_homepage_meta_tags(self): """Meta Tags für Homepage""" meta_tags = { 'title': 'Kasico - Premium Fursuit Shop | Handgefertigte Fursuits', 'description': 'Entdecke handgefertigte, hochwertige Fursuits bei Kasico. Custom Fursuits, Fullsuits, Headsets und mehr. Made in Germany.', 'keywords': 'fursuit, furry, custom fursuit, fullsuit, headset, handgefertigt, germany', 'og_title': 'Kasico - Premium Fursuit Shop', 'og_description': 'Handgefertigte, hochwertige Fursuits made in Germany', 'og_type': 'website', 'og_url': self.base_url, 'canonical_url': self.base_url, } return meta_tags def get_structured_data_product(self, product): """Structured Data für Produkte (JSON-LD)""" structured_data = { "@context": "https://schema.org/", "@type": "Product", "name": product.name, "description": self._clean_description(product.description), "image": self._get_product_image_url(product), "url": f"{self.base_url}{product.get_absolute_url()}", "brand": { "@type": "Brand", "name": "Kasico" }, "offers": { "@type": "Offer", "price": str(product.sale_price if product.on_sale else product.base_price), "priceCurrency": "EUR", "availability": "https://schema.org/InStock" if product.stock > 0 else "https://schema.org/OutOfStock", "seller": { "@type": "Organization", "name": "Kasico" } }, "aggregateRating": { "@type": "AggregateRating", "ratingValue": product.average_rating, "reviewCount": product.reviews.count() } } if product.on_sale: structured_data["offers"]["priceSpecification"] = { "@type": "PriceSpecification", "price": str(product.sale_price), "priceCurrency": "EUR", "valueAddedTaxIncluded": True } return structured_data def get_structured_data_organization(self): """Structured Data für Organisation""" structured_data = { "@context": "https://schema.org", "@type": "Organization", "name": "Kasico", "url": self.base_url, "logo": f"{self.base_url}/static/images/kasico-logo.svg", "description": "Premium Fursuit Shop - Handgefertigte Fursuits made in Germany", "address": { "@type": "PostalAddress", "addressCountry": "DE", "addressLocality": "Germany" }, "contactPoint": { "@type": "ContactPoint", "contactType": "customer service", "email": "info@kasico.de" }, "sameAs": [ "https://twitter.com/kasico_fursuits", "https://www.instagram.com/kasico_fursuits", "https://www.facebook.com/kasico.fursuits" ] } return structured_data def get_structured_data_website(self): """Structured Data für Website""" structured_data = { "@context": "https://schema.org", "@type": "WebSite", "name": "Kasico Fursuit Shop", "url": self.base_url, "description": "Premium Fursuit Shop - Handgefertigte Fursuits made in Germany", "potentialAction": { "@type": "SearchAction", "target": f"{self.base_url}/products/search/?q={{search_term_string}}", "query-input": "required name=search_term_string" } } return structured_data def get_structured_data_breadcrumb(self, breadcrumbs): """Structured Data für Breadcrumbs""" structured_data = { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [] } for i, (name, url) in enumerate(breadcrumbs): structured_data["itemListElement"].append({ "@type": "ListItem", "position": i + 1, "name": name, "item": f"{self.base_url}{url}" }) return structured_data def generate_sitemap_xml(self): """XML Sitemap generieren""" from products.models import Product, Category from django.contrib.sitemaps import Sitemap sitemap_data = { 'urlset': { '@xmlns': 'http://www.sitemaps.org/schemas/sitemap/0.9', 'url': [] } } # Homepage sitemap_data['urlset']['url'].append({ 'loc': self.base_url, 'lastmod': timezone.now().strftime('%Y-%m-%d'), 'changefreq': 'daily', 'priority': '1.0' }) # Produkt-Seiten for product in Product.objects.filter(is_active=True): sitemap_data['urlset']['url'].append({ 'loc': f"{self.base_url}{product.get_absolute_url()}", 'lastmod': product.updated_at.strftime('%Y-%m-%d'), 'changefreq': 'weekly', 'priority': '0.8' }) # Kategorie-Seiten for category in Category.objects.all(): sitemap_data['urlset']['url'].append({ 'loc': f"{self.base_url}{category.get_absolute_url()}", 'lastmod': timezone.now().strftime('%Y-%m-%d'), 'changefreq': 'weekly', 'priority': '0.7' }) # Statische Seiten static_pages = [ ('/products/', 'weekly', '0.8'), ('/gallery/', 'weekly', '0.7'), ('/contact/', 'monthly', '0.5'), ('/about/', 'monthly', '0.5'), ('/faq/', 'monthly', '0.6'), ] for url, changefreq, priority in static_pages: sitemap_data['urlset']['url'].append({ 'loc': f"{self.base_url}{url}", 'lastmod': timezone.now().strftime('%Y-%m-%d'), 'changefreq': changefreq, 'priority': priority }) return sitemap_data def generate_robots_txt(self): """Robots.txt generieren""" robots_content = f"""User-agent: * Allow: / # Sitemap Sitemap: {self.base_url}/sitemap.xml # Disallow admin and private areas Disallow: /admin/ Disallow: /api/ Disallow: /static/admin/ Disallow: /media/admin/ # Allow important pages Allow: /products/ Allow: /gallery/ Allow: /contact/ Allow: /about/ Allow: /faq/ # Crawl delay Crawl-delay: 1 """ return robots_content def _clean_description(self, text, max_length=160): """Beschreibung für Meta Tags bereinigen""" if not text: return "" # HTML Tags entfernen clean_text = strip_tags(text) # Zu lang kürzen if len(clean_text) > max_length: clean_text = clean_text[:max_length-3] + "..." return clean_text def _get_product_image_url(self, product): """Produkt-Bild URL generieren""" if product.image: return f"{self.base_url}{product.image.url}" return f"{self.base_url}/static/images/default-product.jpg" class SEOTemplateTags: """Template Tags für SEO""" @staticmethod def render_meta_tags(meta_tags): """Meta Tags als HTML rendern""" return render_to_string('seo/meta_tags.html', {'meta_tags': meta_tags}) @staticmethod def render_structured_data(structured_data): """Structured Data als JSON-LD rendern""" return render_to_string('seo/structured_data.html', { 'structured_data': json.dumps(structured_data, indent=2) }) @staticmethod def render_social_meta_tags(meta_tags): """Social Media Meta Tags rendern""" return render_to_string('seo/social_meta_tags.html', {'meta_tags': meta_tags}) # SEO Context Processor def seo_context_processor(request): """SEO Context für alle Templates""" seo_manager = SEOManager(request) # Standard SEO für alle Seiten context = { 'seo_manager': seo_manager, 'site_name': 'Kasico', 'site_description': 'Premium Fursuit Shop - Handgefertigte Fursuits made in Germany', 'site_keywords': 'fursuit, furry, custom fursuit, fullsuit, headset, handgefertigt, germany', } # Page-spezifische SEO if hasattr(request, 'resolver_match'): view_name = request.resolver_match.view_name if 'product_detail' in view_name: product = getattr(request, 'product', None) if product: context.update({ 'meta_tags': seo_manager.get_product_meta_tags(product), 'structured_data': seo_manager.get_structured_data_product(product) }) elif 'category_detail' in view_name: category = getattr(request, 'category', None) if category: context.update({ 'meta_tags': seo_manager.get_category_meta_tags(category) }) elif 'home' in view_name: context.update({ 'meta_tags': seo_manager.get_homepage_meta_tags(), 'structured_data': seo_manager.get_structured_data_website() }) return context