1. Po co w ogóle są potrzebne Privacy Policy, Terms i Support
Zacznijmy od przykrej prawdy: dla ChatGPT Store posiadanie publicznej polityki prywatności i danych kontaktowych wsparcia — to nie „dobry ton”, lecz twardy wymóg. W wytycznych OpenAI wprost napisano, że każdy App musi mieć opublikowaną Privacy Policy, w której jasno wyjaśniono, jakie dane są zbierane i jak są używane, a także kontakt do wsparcia.
Ale to nie tylko po to, by „recenzent dał spokój”. Te dokumenty rozwiązują kilka problemów naraz.
Po pierwsze, to podstawowy poziom zaufania dla użytkownika. Widzi on, że za aplikacją stoją żywi ludzie lub firma, są zasady gry i jest miejsce, do którego można zgłosić się z problemem. W świecie, w którym „kolejna usługa AI” pojawia się codziennie, to już przewaga konkurencyjna.
Po drugie, to sformalizowanie tego, co już zrobiliście w architekturze. Wszystko, co rozwiązywaliście w modułach dotyczących bezpieczeństwa, logowania, retencji, usuwania danych i pracy z płatnościami, powinno być opisane również słowami. Jeśli obiecujecie „nie przechowujemy rozmów”, a jednocześnie logujecie cały tool‑input na zawsze, to nie tylko nieładne — to powód do poważnych roszczeń.
Po trzecie, to kolejna warstwa umowy między wami a OpenAI. Store de facto mówi: „Jesteśmy gotowi pokazywać twój App milionom ludzi, ale musisz uczciwie opisać, co z nimi robisz, i być dostępny, gdy coś idzie nie tak”.
Podsumowując: strony prawne — to nie „prawnicy nas zmusili”. To sposób na synchronizację oczekiwań: co robi App, jakie dane dotyka, jaką odpowiedzialność jesteście gotowi ponieść i jak użytkownik może się z wami skontaktować.
2. Gdzie „mieszkają” te adresy URL stron prawnych w ChatGPT App
Technicznie dla ChatGPT App strony prawne — to zwykłe publiczne adresy URL, które podajecie w metadanych aplikacji i w listingu Store. W wytycznych nazywa się je zwykle czymś w rodzaju privacy_policy_url, terms_of_service_url i kontakt do supportu.
Te adresy URL muszą spełniać kilka prostych, ale ważnych warunków:
- Są ulokowane na stabilnej domenie waszego produktu lub firmy. Żadnych tymczasowych linków ngrok — inaczej za tydzień Store będzie prowadzić użytkownika donikąd.
- Są dostępne bez autoryzacji. Użytkownik (i recenzent) muszą móc otworzyć je w przeglądarce bez logowania i skomplikowanych rytuałów.
- Są aktualne i zgodne z rzeczywistością. Jeśli zmieniacie architekturę przetwarzania danych, z czasem trzeba będzie zaktualizować także tekst.
W naszym projekcie szkoleniowym GiftGenius mamy już frontend w Next.js, który wdrażamy, powiedzmy, na Vercel. Logiczne miejsce dla stron prawnych to trasy w rodzaju:
- /legal/privacy
- /legal/terms
- /support
To w gruncie rzeczy po prostu trzy dodatkowe strony w aplikacji, ale właśnie do nich będziecie linkować w formularzu wysyłki App do weryfikacji.
3. Privacy Policy: jak uczciwie opisać, co robicie z danymi
Rola Privacy Policy
Privacy Policy (polityka prywatności, dalej dla zwięzłości — Policy) odpowiada na najważniejsze pytanie: „Co ten App robi z moimi (użytkownika) danymi?” Powinna opisywać, jakie kategorie danych przetwarzacie, skąd pochodzą, po co są potrzebne, gdzie i jak długo są przechowywane, komu są przekazywane i jak użytkownik może poprosić o ich usunięcie.
Specyfika ChatGPT Apps polega na tym, że dla użytkownika ważne jest zrozumienie, co dokładnie otrzymujecie z czatu. OpenAI wyraźnie podkreśla: wasz App nie powinien próbować odtworzyć całej rozmowy, lecz pracować tylko z tymi fragmentami, które model albo użytkownik wyraźnie przekazał do narzędzi. To również warto zaznaczyć w Policy.
Zaczynamy nie od tekstu, lecz od architektury
Zanim napiszecie choć jedno słowo prawne, warto spojrzeć na swój App oczami SRE/architekta: jakie dane faktycznie przepływają przez system.
Dla naszego przykładu — GiftGenius — może to wyglądać tak:
| Kategoria danych | Źródło | Miejsce przechowywania | Okres / zachowanie |
|---|---|---|---|
| Tekst zapytania (fragment z czatu) | Wywołanie narzędzia (tool) z ChatGPT | Logi żądań w backendzie | N dni lub usuwamy od razu |
| Prezenty wybrane przez użytkownika | Działania w widżecie | Baza GiftGenius | Przechowujemy do usunięcia konta |
| Email użytkownika (jeśli jest OAuth) | Dostawca uwierzytelniania | Baza użytkowników | Dopóki konto jest aktywne |
| Metryki techniczne (IP, znacznik czasu, błędy) | Żądania HTTP | Logi / system monitoringu | N dni zgodnie z polityką logów |
Taką tabelkę można wprowadzić bezpośrednio do dokumentacji projektu (np. w /docs): przyda się i do developmentu, i do modułu Security, i do samej Policy.
Następnie „tłumaczymy” tę strukturę na język zrozumiały dla użytkownika.
Struktura Privacy Policy dla GiftGenius
W projekcie szkoleniowym nie trzeba pisać eposu na 20 stron — wystarczy zwięzła, ale uczciwa struktura. Zwykle wyróżnia się kilka sekcji:
- Wprowadzenie: kim jesteście i czym jest App.
- Jakie dane zbieracie.
- Jak je wykorzystujecie.
- Komu je przekazujecie.
- Gdzie i jak długo je przechowujecie.
- Prawa użytkownika (w tym żądanie usunięcia).
- Kontakt w sprawach prywatności.
Warto pamiętać, że nawet w projekcie szkoleniowym to nie tylko „szablon”. W module o bezpieczeństwie przemyśleliście już okres przechowywania logów, politykę usuwania, backupy — teraz trzeba to starannie sformułować.
Najprostsza implementacja strony w Next.js
Zróbmy stronę /legal/privacy w naszej aplikacji. W App Router to dosłownie jeden plik:
// app/legal/privacy/page.tsx
export default function PrivacyPage() {
return (
<main className="mx-auto max-w-3xl p-8 prose">
<h1>Privacy Policy – GiftGenius</h1>
<p>Last updated: {new Date().toLocaleDateString()}</p>
{/* dalsze sekcje polityki */}
</main>
);
}
Ten przykład jest celowo prosty: cel — ustalić statyczny URL. W prawdziwym projekcie tekst polityki niemal zawsze trzymany jest osobno (np. w pliku .md) i ładowany, aby nie rozlewać ton tekstu po JSX.
Na przykład można zrobić standardowy loader:
// app/legal/privacy/page.tsx
import policyHtml from "./policy.html"; // wcześniej zbudowany HTML
export default function PrivacyPage() {
return (
<main
className="mx-auto max-w-3xl p-8 prose"
dangerouslySetInnerHTML={{ __html: policyHtml }}
/>
);
}
Uwagi w stylu „nie róbcie tego bez zrozumienia” są tu na miejscu: dangerouslySetInnerHTML jest bezpieczne tylko wtedy, gdy kontrolujecie źródło HTML (np. budujecie je sami z markdown w CI).
Powiązanie z rzeczywistymi procesami
Najważniejsze: nie wolno pisać w Policy tego, czego nie macie w kodzie. Jeśli deklarujecie, że:
- nie przechowujecie tekstów zapytań dłużej niż 7 dni;
- na żądanie użytkownika całkowicie usuwacie jego profil;
- nie używacie tych danych do trenowania własnych modeli,
wówczas musicie mieć:
- ustawienia retencji w logach;
- endpoint lub proces administracyjny usuwania użytkownika;
- brak kodu, który wylewa logi do zewnętrznego magazynu „dla Data Science”.
I odwrotnie: jeśli włączyliście metryki użycia, eksperymenty A/B lub analitykę po krajach, trzeba uczciwie o tym powiedzieć w Policy. I dać użytkownikowi przynajmniej podstawowe prawa: dowiedzieć się, co jest przechowywane, i zażądać usunięcia.
Z danymi i Privacy Policy uporaliśmy się. Pozostaje ustalić nie tylko przetwarzanie danych, ale i same „zasady gry” — to zadanie dla Terms.
4. Terms of Use / Service: zasady i dysklaimery AI
Po co Terms, skoro mamy już Policy
Privacy Policy odpowiada na pytanie „co robicie z danymi”. Terms Of Use/Service (dalej — Terms) — na pytanie „na jakich warunkach w ogóle można korzystać z App”. To umowa prawna między wami a użytkownikiem.
Opisywane są w nich:
- czym jest GiftGenius i jakie funkcje zapewnia;
- jakie działania użytkownika są dozwolone, a jakie — nie;
- gdzie przebiegają „granice magii” AI (dysklaimery);
- jakie macie ograniczenia odpowiedzialności;
- jak rozwiązywane są spory i jaka obowiązuje jurysdykcja.
Dla aplikacji AI szczególnie ważne są dwa elementy: dysklaimer dotyczący dokładności oraz ograniczenie odpowiedzialności.
Specyfika AI: „model może się mylić”
Nasz GiftGenius daje rekomendacje prezentów. To miłe i względnie bezpieczne, ale nawet tu można wpaść na minę: użytkownik poprosił o „prezent dla osoby z alergią na orzechy”, model wygenerował coś nieodpowiedniego, osoba ucierpiała — wszyscy są nieszczęśliwi.
Jasne, że Terms nie są kamizelką kuloodporną na wszelkie ryzyka, ale jasno utrwalają:
- że wyniki generuje AI i mogą być niedokładne, nieaktualne lub po prostu dziwne;
- że użytkownik musi samodzielnie weryfikować ważne informacje, zwłaszcza związane ze zdrowiem, finansami i innymi wrażliwymi obszarami;
- że nie dajecie żadnych gwarancji „idealności” rekomendacji i nie odpowiadacie za wykorzystanie wyniku niezgodnie z przeznaczeniem.
Formułowania trzeba będzie potem dopracować z prawnikiem, ale dla dewelopera ważne jest zrozumienie idei.
Niuanse commerce
Jeśli wasz App wykonuje jakiekolwiek operacje płatnicze (moduł o ACP i commerce będzie jeszcze omawiany głębiej, ale w kursie to uwzględniono), w Terms trzeba starannie opisać:
- przez kogo przechodzą płatności (Stripe, ACP, inny system);
- jakie dane o płatnościach w ogóle widzicie;
- jakie są warunki zwrotów i anulowania zamówień;
- co konkretnie uznaje się za udaną transakcję.
Zalecenie platformy w ogólnym przypadku — jasno wskazać, że dane karty są przetwarzane przez dostawcę płatności, a nie wasz serwer, a wy przechowujecie tylko minimum (np. ID transakcji).
Implementacja /legal/terms w Next.js
Technicznie wszystko jest bardzo podobne do Privacy Policy. Zakładamy stronę:
// app/legal/terms/page.tsx
export default function TermsPage() {
return (
<main className="mx-auto max-w-3xl p-8 prose">
<h1>Terms of Use – GiftGenius</h1>
<p>Last updated: {new Date().toLocaleDateString()}</p>
{/* sekcje: opis usługi, ograniczenia, dysklaimer AI, odpowiedzialność */}
</main>
);
}
I, podobnie jak w przypadku Policy, lepiej trzymać tekst w oddzielnym pliku lub CMS, a w kodzie mieć minimum znaczników.
Można wynieść wspólny layout dla stron prawnych:
// app/legal/LegalLayout.tsx
export function LegalLayout(props: { title: string; children: React.ReactNode }) {
return (
<main className="mx-auto max-w-3xl p-8 prose">
<h1>{props.title}</h1>
<p>Last updated: {new Date().toLocaleDateString()}</p>
{props.children}
</main>
);
}
A następnie używać jej zarówno dla Policy, jak i Terms. To nie kwestia „ładnego kodu”, lecz tego, żeby nie zapomnieć o dacie aktualizacji i utrzymać spójny styl.
5. Support / Contact: gdzie użytkownik ma się zgłosić z problemem
Minimum i „dobry ton”
W wytycznych OpenAI wskazano, że App musi mieć zrozumiały sposób kontaktu z deweloperem w sprawach wsparcia. Może to być prosty e‑mail, ale musi istnieć, przyjmować wiadomości i przynajmniej czasem doczekiwać się odpowiedzi.
Minimalna wersja dla projektu szkoleniowego:
- oddzielna strona /support z krótkim opisem i mailto:support@yourdomain.com.
Bardziej dojrzała wersja:
- formularz kontaktowy;
- link do dokumentacji lub Help Center;
- ewentualnie — link do Slack/Discord, jeśli budujecie społeczność wokół produktu.
Strona /support w Next.js
Zacznijmy od zupełnie prostego wariantu:
// app/support/page.tsx
export default function SupportPage() {
return (
<main className="mx-auto max-w-xl p-8 prose">
<h1>GiftGenius Support</h1>
<p>
If you have issues or questions, email us at{" "}
<a href="mailto:support@giftgenius.app">support@giftgenius.app</a>.
</p>
</main>
);
}
Nieco bardziej zaawansowana wersja — dodać prosty formularz:
// app/support/page.tsx
"use client";
export default function SupportPage() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// tutaj będzie wywołanie API, które wyśle e-mail/ticket
};
return (
<main className="mx-auto max-w-xl p-8 prose">
<h1>GiftGenius Support</h1>
<form onSubmit={handleSubmit}>
<input name="email" placeholder="Your email" className="border p-2 w-full" />
<textarea name="message" placeholder="How can we help?" className="border p-2 w-full mt-2" />
<button type="submit" className="mt-4 px-4 py-2 border rounded">
Send
</button>
</form>
</main>
);
}
Nawet jeśli nie wdrożycie prawdziwego backendu dla tego formularza w projekcie szkoleniowym, samo posiadanie zrozumiałego URL i struktury strony już przybliża was do wymogów Store.
Powiązanie z incident management
Strona Support — to nie tylko „gdzie pisać, jeśli wszystko padło”, ale i część waszej operacyjnej rzeczywistości. W późniejszych modułach będzie mowa o incydentach i operacyjnym życiu App. Wtedy strona Support stanie się „drzwiami wejściowymi” dla użytkowników: przez nią spływają zgłoszenia błędów, pytania, żądania usunięcia danych. Teraz ważne jest przynajmniej to, by takie drzwi istniały i nie prowadziły do „404 Not Found”.
6. Integracja stron prawnych w aplikację i listing
Wspólna konfiguracja adresów URL w projekcie
Aby nie rozsmarowywać „magicznych stringów” z URL po kodzie, wygodnie jest wprowadzić prostą konfigurację:
// lib/appConfig.ts
export const legalLinks = {
privacy: "https://giftgenius.app/legal/privacy",
terms: "https://giftgenius.app/legal/terms",
support: "https://giftgenius.app/support",
} as const;
Te same adresy URL wykorzystacie:
- w ustawieniach ChatGPT App (metadane);
- na landing page produktu;
- w e‑mailach, jeśli wdrożycie powiadomienia.
Wewnątrz widżetu możecie dać użytkownikowi szybki dostęp do tych stron przez openExternal.
// wewnątrz widżetu React GiftGenius
import { legalLinks } from "../lib/appConfig";
function FooterLinks() {
const handleOpen = (url: string) => {
window.openai?.openExternal({ url }); // Apps SDK helper
};
return (
<footer className="mt-4 text-xs text-gray-500">
<button onClick={() => handleOpen(legalLinks.privacy)}>Privacy</button>
<span> · </span>
<button onClick={() => handleOpen(legalLinks.terms)}>Terms</button>
</footer>
);
}
W prawdziwym kodzie widżetu lepiej użyć hooka useOpenExternal z Apps SDK; tutaj dla zwięzłości pokazano bezpośrednie wywołanie przez window.openai.
Dzięki temu zwiększacie przejrzystość: użytkownik może z widżetu jednym kliknięciem przejść do dokumentów prawnych, zamiast szukać ich gdzieś w Store.
Przepływ użytkownika i recenzenta
Spójrzmy na przebieg interakcji w postaci małego schematu:
flowchart TD A[Strona listingu w ChatGPT Store] --> B[Użytkownik czyta opis App] B --> C[Otwiera Privacy / Terms z linku] B --> D[Instaluje / zaczyna używać App] D --> E[Uruchamia widżet GiftGenius] E --> F["W razie potrzeby klika 'Support' lub 'Privacy'"]
Recenzent ChatGPT Store przechodzi podobną ścieżkę, tylko nieco bardziej podejrzliwie. Sprawdza:
- co jest napisane w listingu;
- co obiecują Policy i Terms;
- jak zachowuje się App w realnym scenariuszu;
- czy zachowanie pokrywa się z tym, co napisaliście.
Jeśli wszystko jest uczciwe i przewidywalne — szansa przejścia weryfikacji znacząco rośnie.
7. Ćwiczenie praktyczne dla waszego App
Aby nie pozostać w teorii, warto od razu stworzyć szkice dokumentów dla swojej aplikacji.
Proponowane podejście.
Najpierw na poziomie architektury opiszcie:
- jakie kategorie danych przetwarzacie (tekst zapytania, zamówienia, email, metryki);
- czy przechowujecie tekstowe zapytania, a jeśli tak — jak długo;
- jakie zewnętrzne usługi są podłączone (hosting, baza, system płatności, analityka).
Po tym:
- Ułóżcie strukturę Privacy Policy z sekcjami „co zbieramy”, „dlaczego”, „komu przekazujemy”, „jak długo przechowujemy”, „jak usunąć dane”.
- Ułóżcie strukturę Terms: opis usługi, zasady korzystania, ograniczenia (zakaz treści i nadużyć), dysklaimer AI, ograniczenie odpowiedzialności, linki do Policy.
- Stwórzcie stronę /support z krótkim tekstem i adresem e‑mail.
- Dodajcie do projektu lib/appConfig.ts z URL-ami stron prawnych i wykorzystujcie je w widżecie oraz w zewnętrznych linkach.
Nawet jeśli teksty będą na razie szkicowe i planujecie „później pokazać je prawnikowi”, wykonacie już ważną pracę: powiążecie implementację techniczną z opisem prawnym.
8. Typowe błędy przy przygotowaniu stron prawnych
Błąd nr 1: skopiować losową politykę prywatności z internetu i nie zmieniać.
Czasem kusi, by wziąć pierwszą lepszą politykę prywatności, podmienić nazwę produktu i uznać sprawę za zamkniętą. Problem w tym, że taki tekst niemal na pewno nie odpowiada waszej architekturze. Mogą się w nim znajdować sekcje o aplikacji mobilnej, powiadomieniach push czy konkretnych systemach analitycznych, których u was nie ma, a z drugiej strony — może nie być nic o serwerze MCP, logach narzędzi i pracy przez ChatGPT. Recenzent zauważy rozbieżności, a użytkownicy poczują, że tekst jest „o kimś innym”.
Błąd nr 2: obiecywać w Policy coś, czego nie ma w kodzie.
Klasyczny przykład — fraza „usuwamy wszystkie wasze dane na pierwsze żądanie”, podczas gdy w kodzie nie ma ani endpointu usuwania, ani nawet mechanizmu wyszukania danych konkretnego użytkownika. To samo dotyczy okresów przechowywania logów i zdań „nie przechowujemy tekstu waszych wiadomości”, jeśli w rzeczywistości wrzucacie tool‑input do systemu logów bez retencji. Taka niespójność jest niebezpieczna zarówno dla weryfikacji, jak i dla realnych użytkowników.
Błąd nr 3: ignorować specyfikę AI w Terms.
Jeśli w Terms nie ma ani słowa o tym, że odpowiedzi generuje model i mogą być niedokładne, użytkownik może oczekiwać od waszego App „ostatecznej prawdy”. Dla usług rekomendacyjnych (prezenty, podróże, dobór towarów) to jeszcze bywa znośne, ale dla medycyny, finansów czy porad prawnych taki brak może skończyć się bardzo źle. Lepiej jasno i uczciwie opisać ograniczenia i odpowiedzialność.
Błąd nr 4: strona Support bez realnego kontaktu lub z martwym adresem.
Strona /support, która prowadzi do mailto:hello@example.com, gdzie nikt nigdy nie zagląda, formalnie istnieje, ale w praktyce jest bezużyteczna. Użytkownik nie otrzymuje odpowiedzi, raporty o błędach giną, a reputacja App spada. Platforma również oczekuje, że będziecie odpowiadać na skargi i problemy. Nawet jeśli jesteście małym zespołem, ważne jest, by przynajmniej co kilka dni przeglądać skrzynkę i reagować.
Błąd nr 5: zapominać o dacie i wersji dokumentów.
Zdarza się, że na stronach prawnych w ogóle nie ma informacji o dacie aktualizacji. Dla recenzenta to niepokojący znak: nie wiadomo, czy dokumenty odpowiadają aktualnemu stanowi produktu. Prosty blok „Last updated: …” rozwiązuje problem zarówno dla was, jak i dla użytkowników, a także pomaga prowadzić historię zmian, jeśli z czasem dopracowujecie architekturę, a co za tym idzie — tekst Policy/Terms.
GO TO FULL VERSION