Web-Präsenz und SEO
Zweck
Beide Stores verlangen URLs, bevor sie eine Einreichung zulassen: Datenschutzerklärung, Support, Kontolöschung und für App-Links die .well-known-Dateien. Dieser Skill erstellt eine kleine, schnelle statische Seite, die zuerst diese Formulare erfüllt und sie dann auffindbar macht (Suchmaschinen, Link-Vorschauen, KI-Assistenten) – ohne Tracker, Dark Patterns oder Zahlen, die die App nicht untermauern kann.
Führen Sie dies vor dem Store-Listing und den Datenschutzformularen (listing-and-aso, privacy-and-declarations) durch: Sie benötigen Live-URLs.
Voraussetzungen
- Eine Domain, die Sie kontrollieren, mit DNS-Zugang (Cloudflare wird in den Beispielen verwendet; jeder Host funktioniert, wenn er Header setzen und Dateien ohne Weiterleitungen ausliefern kann).
- Die endgültigen App-Identifikatoren und Signaturdaten aus
identity-and-signing(Team-ID, Bundle-ID, Paketname, Play App Signing SHA-256). - Der Datenschutztext, der aus dem Code/SDK-Scan (
privacy-and-declarations) abgeleitet wurde, sowie der Löschvorgang, der tatsächlich in der App existiert. - Preise, die aus den Stores ausgelesen wurden (
subscriptions-and-payments), niemals aus dem Gedächtnis getippt. - Node.js 18+ für die Skripte in scripts/.
1. Von den Stores benötigte Seiten
Checkliste mit jedem Store-Feld → URL: references/store-url-checklist.md.
| Seite | Pfad (vorgeschlagen) | Regeln |
|---|---|---|
| Datenschutzerklärung | /privacy | Öffentlich, kein Login, keine Geo-Sperre, HTML (kein PDF), nennt die App, stimmt mit den Datenschutzantworten im Store überein |
| AGB | /terms | Erforderlich, wenn Sie Abos verkaufen (Apple's Standard-EULA oder eigene; in der App und im Listing verlinken) |
| Support / Kontakt | /support | Ein echter Weg, um Sie zu erreichen (E-Mail oder Formular), nicht nur ein FAQ |
| Kontolöschung (Web) | /delete-account | Google Play benötigt diese URL. Nennt die App wie im Listing, ermöglicht dem Benutzer, die Löschung auf der Seite selbst zu beantragen, sagt, was gelöscht wird, was aufbewahrt wird und wie lange, und dass ein Store-Abo separat gekündigt werden muss |
- Apple verlangt, dass die Löschung innerhalb der App beginnt (Richtlinie 5.1.1(v)); eine Webseite ersetzt dies nicht. Play verlangt sowohl den In-App-Pfad als auch die Web-URL. Dokumentation: Apple Kontolöschung, Play Kontolöschung, Play Datenschutz-URL-Regeln.
- Ohne Anmeldung und stabil. Keine Cookie-Wall, kein Login, kein JavaScript erforderlich, um den Text zu lesen. Benennen Sie Pfade nach der Einreichung nicht um; falls nötig, halten Sie eine 301 vom alten Pfad.
- Pro Sprache. Eine URL pro Sprache (
/privacy,/de/privacy) mithreflang; App Store Connect erlaubt eine Datenschutz-URL pro Lokalisierung. Wenn eine Seite nicht übersetzt ist, verlinken Sie die Seite in der Standardsprache, nicht auf eine 404. - Zeigen Sie das „Zuletzt aktualisiert“-Datum auf rechtlichen Seiten und behalten Sie alte Versionen in der Versionskontrolle.
2. App-Links Hosting
Vorlagen für die Dateien selbst befinden sich in identity-and-signing/templates/. Dieser Abschnitt behandelt das Ausliefern.
https://<domain>/.well-known/apple-app-site-associationund/.well-known/assetlinks.json: HTTP 200,Content-Type: application/json, keine Weiterleitung (nicht http→https, nicht apex→www, kein abschließender Schrägstrich), keine Authentifizierung, keine Bot-Challenge-Seite.- Entscheiden Sie sich einmal für apex vs
www. Liefern Sie die Dateien auf jedem Host aus, der in den Berechtigungen / Intent-Filtern aufgeführt ist; leiten Sie den anderen Host nur für Seiten weiter, niemals für/.well-known/. - Statische Hosts liefern die erweiterungslose AASA oft als
application/octet-stream. Routen Sie/.well-known/*durch den Worker (siehe Vorlage) oder setzen Sie den Header explizit, und prüfen Sie dann mitscripts/check-site.mjs. - Stellen Sie die
.well-known-Dateien vor dem App-Build bereit, der die Domain beansprucht. Apple ruft AASA über sein CDN ab, daher können Änderungen eine Weile dauern, bis sie sichtbar sind.
Einladungs-/Empfehlungsseiten (/i/<code>)
- Der Worker validiert den Code gegen das exakte Alphabet und die Länge, die das Backend ausgibt, und füllt dann eine Vorlage. Nichts anderes von der URL gelangt ins HTML.
- Wenn die App installiert ist, öffnen Universal Links / App-Links sie direkt (der Pfad muss in den
componentsder AASA und im Android Intent-Filter sein). Wenn nicht, zeigt die Seite beide Store-Buttons und einen „Code kopieren“-Button als manuellen Fallback. - Android: Hängen Sie den Code an die Play-URL als
&referrer=<url-kodiertes key=value>an und lesen Sie ihn in der App mit der Play Install Referrer API. iOS hat keinen Install-Referrer; bitten Sie den Benutzer, den Code einzufügen, oder füllen Sie ihn aus der Zwischenablage vor nur nach einem expliziten Tipp. - Header:
X-Robots-Tag: noindex,Cache-Control: private, no-store,Referrer-Policy: no-referrer. Lassen Sie/i/aus der Sitemap. Verbieten Sie es nicht inrobots.txt: Ein Crawler, der die Seite nicht abrufen kann, sieht dasnoindexnie.
3. Landing-Page
- Gleiche visuelle Sprache wie die Store-Screenshots (Farben, Schriftart, dieselben echten UI-Karten). Ein Besucher, der von der Seite kommt, sollte die Store-Seite wiedererkennen.
- Store-Badges nur in der offiziellen Grafik, unverändert, mit dem erforderlichen Abstand und Wortlaut; verlinken Sie direkt zum Listing. Regeln: Apple Marketing-Richtlinien, Google Play Badges.
- Vor dem Start: eine Zeile „Coming soon to the App Store and Google Play“, nicht drei deaktivierte Badges. Beim Start (nachdem die Veröffentlichung live ist): tauschen Sie echte Badge-Links ein, fügen Sie das Smart App Banner Meta hinzu (Dokumentation), aktualisieren Sie
llms.txtund das JSON-LD. Halten Sie dies als ein einzelnes Konfigurationsflag, damit es eine Änderung ist. FREIGABE vor dem Umschalten. - Ehrliche Preise. Preise kommen aus einer Datei, die aus dem Store-Rücklesen generiert wurde. Seiten enthalten Platzhalter (
%%PRICE_MONTHLY%%); der Worker füllt sie basierend auf dem Land des Besuchers (request.cf.country) und sagt für Länder außerhalb der Tabelle „der Store zeigt den genauen Preis in Ihrer Währung“. Die Seiten-Sprache entscheidet nie über die Währung. Keine durchgestrichenen „war“-Preise, keine gefälschten Countdowns, nichts vorangekreuztes. - Schnell und zugänglich. Text in HTML (nicht durch JS gerendert), eine CSS-Datei, wenig oder kein JS, selbst gehostete Schriftarten mit
font-display: swap, Hero-Bild mit Größenangabe undfetchpriority="high". Ziele: LCP < 2,5 s, CLS < 0,1, INP < 200 ms (Web Vitals). Kontrast und Fokus-Zustände gemäß WCAG 2.2;prefers-reduced-motionwird respektiert. - Analytik. Bevorzugen Sie keine oder serverseitige/cookielose Zählungen (Edge-Logs, datenschutzfreundliche Analytik ohne Identifikatoren). Wenn Sie keine Cookies setzen und keine Drittanbieter-Skripte laden, benötigen Sie kein Cookie-Banner; zeigen Sie keins „nur für den Fall“. Wenn Sie einen Tracker hinzufügen, müssen das Consent-Banner, die Datenschutzerklärung und die Store-Datenschutzantworten alle gemeinsam geändert werden.
4. Bilder für Social Sharing
- Ein Open Graph-Bild pro Sprache: 1200×630 PNG/JPG, unter ~1 MB, Text groß genug, um in Thumbnail-Größe lesbar zu sein. Absolute
https://-URLs inog:imageundtwitter:image, plusog:image:width/height/alt,og:title,og:description,og:url,twitter:card=summary_large_image. Spezifikation: ogp.me, Meta-Sharing-Guide. - Nachrichten-Apps cachen Vorschauen aggressiv zwischern. Nach dem Ändern eines Bildes geben Sie ihm einen neuen Dateinamen (oder
?v=2), und führen Sie dann ein erneutes Scrapen im Sharing Debugger durch („Erneut scrapen“). WhatsApp und andere Messenger behalten ihre eigenen Caches ohne öffentliches Aktualisierungstool, daher ist eine neue Bild-URL die zuverlässige Lösung; testen Sie, indem Sie den Link in einem neuen Chat senden.
5. Technische SEO
- Title (≈50–60 Zeichen, Marke + was sie tut) und Meta-Beschreibung (≈150–160 Zeichen) eindeutig pro Seite und Sprache. Title-Links, Snippets.
- hreflang: jede Sprachversion listet alle Versionen einschließlich sich selbst plus
x-defaultauf; Paare müssen reziprok sein. Lokalisierte Versionen. - Canonical: selbstreferenzierend, absolut, auf der endgültigen (nicht weiterleitenden) URL. Canonicalisierung.
- Sitemap mit nur 200, indexierbaren, kanonischen URLs und einem echten
<lastmod>(Datum, an dem sich der Inhalt geändert hat, z. B. aus git, nicht die Build-Zeit). Vorlage, Dokumentation. - robots.txt: Vorlage, Einführung. robots.txt steuert das Crawlen, nicht das Indexieren; verwenden Sie
noindexfür Seiten, die nicht in den Ergebnissen erscheinen sollen. - Strukturierte Daten (JSON-LD): Organization, WebSite, MobileApplication; FAQPage nur für ein FAQ, das auf der Seite sichtbar ist. Beispiele und Regeln: references/structured-data.md.
- Nicht-Produktions-Hosts (Preview,
*.workers.dev) sendenX-Robots-Tag: noindex.
6. Auffindbarkeit
- Google Search Console: Fügen Sie eine Domain-Eigenschaft hinzu, fügen Sie den
google-site-verificationTXT-Eintrag am Apex hinzu, verifizieren Sie, reichen Sie die Sitemap ein, fordern Sie die Indexierung der Startseiten an. Besitz verifizieren. - Bing Webmaster Tools: Importieren Sie aus der Search Console, oder verifizieren Sie mit dem DNS-Eintrag, den Bing angibt (ein CNAME), und reichen Sie dann die Sitemap ein. Seite hinzufügen und verifizieren.
- IndexNow (Bing, Yandex, Seznam, Naver und andere; nicht Google): Hosten Sie
/<key>.txtmit dem Schlüssel, stellen Sie bereit, führen Sie dannnode scripts/indexnow-ping.mjs(Trockenlauf) und--sendaus. Das Skript prüft zuerst, ob die Schlüsseldatei live ist. Protokoll. - KI-Crawler und llms.txt: Entscheiden Sie pro Bot, ob Such-/Antwort-Bots und Trainings-Bots erlaubt sind (Entscheidung des Eigentümers, FREIGABE). Bot-Liste, Zwecke und offizielle Links: references/ai-crawlers.md. Fügen Sie eine kurze llms.txt mit der Produktzusammenfassung und den wichtigsten URLs hinzu, keine Preise.
DNS-Einträge sind gemeinsame Infrastruktur: Fügen Sie den neuen Eintrag hinzu; bearbeiten oder löschen Sie niemals bestehende TXT/SPF/MX-Einträge. FREIGABE vor jeder DNS-Änderung.
7. Bereitstellung (Cloudflare Worker Beispiel)
Vorlage: templates/worker.example.js. Sie liefert .well-known-Dateien mit dem richtigen Typ und ohne Weiterleitung, füllt länderspezifische Preis-Platzhalter, rendert /i/<code>, fügt Sicherheitsheader und noindex auf Nicht-Produktions-Hosts hinzu.
Zwei Speicheroptionen:
- Workers Static Assets (am einfachsten):
"assets": { "directory": "./dist", "binding": "ASSETS", "run_worker_first": true }inwrangler.jsonc; der Worker ruftenv.ASSETS.fetch()auf. Dokumentation. - KV (content-addressed): Der Build schreibt Dateien unter ihren Hash und eine
manifest.js(Pfad → Hash, Typ); laden Sie mitwrangler kv bulk putvor dem Bereitstellen des Workers hoch, damit das neue Manifest nie auf eine fehlende Datei zeigt. KV-Befehle.
Schritte:
node build.mjs→dist/(bricht bei fehlendem Übersetzungsschlüssel oder ungefülltem Platzhalter (außer Preis-Platzhaltern) ab).- Unit-Tests (
node --test): Führen Sie dasfetchdes Workers gegen Dummy-Assets aus. Abdecken: AASA/assetlinks 200 +application/json+ keine Weiterleitung;www/http-Weiterleitung nur für Seiten;/i/<bad>→ 404,/i/<good>→ noindex + no-store; jede Preisregion füllt jeden Platzhalter (kein%%übrig); fehlerhafte Prozent-Kodierung → 404, nicht 500. - Vorschau:
npx wrangler deploy --dry-run, oder auf einen Vorschau-Host bereitstellen undnode scripts/check-site.mjs https://<preview-host>ausführen. - FREIGABE — Produktions-Deploy (
npx wrangler deploy). Fixieren Sieaccount_id,nameund Routen inwrangler.jsonc, damit der Befehl nicht auf ein anderes Projekt auf einem gemeinsamen Account abzielen kann. - Nach dem Deploy:
node scripts/check-site.mjs https://example.com --invite <sample code>, dann den IndexNow-Ping.
Entscheidungspunkte, die menschliche Genehmigung benötigen
- Produktions-Deploys und DNS-Änderungen.
- Formulierung rechtlicher Seiten (Datenschutz, AGB, Löschung); der Eigentümer genehmigt jede Änderung.
- KI-Trainings-Crawler erlauben/verbieten.
- Der Schalter „Coming Soon“ → „Download“ und alle auf der Seite angezeigten Preise.
- Hinzufügen von Analytik, einer Warteliste oder allem, das personenbezogene Daten sammelt.
Überprüfung
node scripts/check-site.mjs https://example.com --paths /privacy,/terms,/support,/delete-accountbeendet sich mit 0: Erforderliche Seiten 200 ohne Anmeldung, AASA/assetlinks JSON ohne Weiterleitung, OG-Tags mit erreichbaren absoluten Bildern, reziprokes hreflang, Sitemap-URLs alle 200.- Jede URL in der Store-URL-Checkliste öffnet sich in einem privaten Fenster auf einem Telefon.
- Rich Results Test und Schema Markup Validator zeigen keine Fehler; PageSpeed Insights mobile LCP < 2,5 s.
- Search Console: Sitemap „Erfolg“; Bing: IndexNow-Übermittlungen sichtbar.
Häufige Fallstricke
- Datenschutz-URL, die auf einen Login, ein PDF oder eine allgemeine Unternehmensrichtlinie weiterleitet, die die App nie nennt.
- Löschseite, die nur sagt „Löschen Sie in der App“ (Play möchte einen Antragspfad auf der Seite) oder vergisst, die Kündigung des Store-Abos zu erwähnen.
- AASA, die über apex→www-Weiterleitung, als
text/htmloder hinter einer Bot-Challenge ausgeliefert wird. Disallow: /i/in robots.txt zusammen mit einemnoindex-Header, den Crawler dann nie sehen.- Preise, die pro Sprache fest codiert sind (EUR auf der deutschen Seite für einen Besucher in der Schweiz) oder nach einer Preisänderung im Store als veraltete Zahlen übrig bleiben.
aggregateRatingfür eine neue App erfunden, oderoffersmit einem Preis, der nur in einem Land wahr ist.- OG-Bild, das auf einen 404, eine langsame CDN-URL oder eine zu lange URL (WhatsApp limitiert auf ca. 2000 Zeichen) zeigt.