Zestawy powiązanych witryn to mechanizm platformy internetowej, który pomaga przeglądarkom zrozumieć relacje między kolekcją domen. Umożliwia to przeglądarkom podejmowanie kluczowych decyzji dotyczących włączania określonych funkcji witryny (np. zezwalania na dostęp do plików cookie innych witryn) i przedstawiania tych informacji użytkownikom.
Wiele witryn korzysta z wielu domen, aby zapewnić użytkownikom spójne wrażenia. Organizacje mogą chcieć utrzymywać różne domeny najwyższego poziomu w wielu przypadkach użycia, np. domeny specyficzne dla danego kraju lub domeny usługowe do hostowania obrazów lub filmów. Zestawy powiązanych witryn umożliwiają witrynom udostępnianie danych w różnych domenach z określonymi ustawieniami.
Co to jest zestaw powiązanych witryn?
Zestaw powiązanych witryn to zbiór domen, w przypadku których istnieje jedna „witryna główna” i potencjalnie wiele „witryn członkowskich”.
W przykładzie poniżej primary zawiera listę domeny podstawowej, a associatedSites – listę domen, które spełniają wymagania powiązanego podzbioru.
{
"primary": "https://primary.com",
"associatedSites": ["https://associate1.com", "https://associate2.com", "https://associate3.com"]
}
Zestawy powiązanych witryn są wymienione w publicznym pliku JSON hostowanym w serwisie GitHub. Jest to kanoniczne źródło wszystkich zatwierdzonych zbiorów. Przeglądarki korzystają z tego pliku, aby określić, czy witryny należą do tego samego zestawu powiązanych witryn.
Tylko osoby z uprawnieniami administracyjnymi do domeny mogą utworzyć zestaw z tą domeną. Zgłaszający muszą zadeklarować relację między każdym „elementem zestawu” a „głównym elementem zestawu”. Zbiory mogą obejmować różne typy domen i muszą być częścią podzbioru opartego na przypadku użycia.
Jeśli Twoja aplikacja zależy od dostępu do plików cookie innych witryn (nazywanych też plikami cookie innych firm) w witrynach należących do tego samego zestawu powiązanych witryn, możesz użyć interfejsu Storage Access API (SAA) i interfejsu requestStorageAccessFor API, aby poprosić o dostęp do tych plików cookie. W zależności od podzbioru, do którego należy witryna, przeglądarka może obsługiwać żądanie w inny sposób.
Aby dowiedzieć się więcej o procesie przesyłania zestawów i wymaganiach z nim związanych, zapoznaj się z wytycznymi dotyczącymi przesyłania. Przesłane zestawy przejdą różne kontrole techniczne, aby zweryfikować przesłane dane.
Przypadki użycia zestawów powiązanych witryn
Zestawy powiązanych witryn są przydatne w sytuacjach, gdy organizacja potrzebuje wspólnej tożsamości w różnych witrynach najwyższego poziomu.
Oto niektóre przypadki użycia zestawów powiązanych witryn:
- Dostosowywanie do kraju korzystanie ze zlokalizowanych witryn przy jednoczesnym poleganiu na wspólnej infrastrukturze (np.witryna example.co.uk może korzystać z usługi hostowanej przez example.ca);
- Integracja domeny usługi Korzystanie z domen usług, z którymi użytkownicy nigdy nie wchodzą w bezpośrednią interakcję, ale które świadczą usługi w witrynach tej samej organizacji (np. example-cdn.com).
- Oddzielanie treści użytkowników Dostęp do danych w różnych domenach, które ze względów bezpieczeństwa oddzielają treści przesłane przez użytkowników od innych treści w witrynie, przy jednoczesnym umożliwieniu domenie w piaskownicy dostępu do plików cookie uwierzytelniania (i innych). Jeśli udostępniasz nieaktywne treści przesłane przez użytkowników, możesz bezpiecznie hostować je w tej samej domenie, stosując sprawdzone metody.
- Treści umieszczone na stronach, które wymagają uwierzytelnienia obsługiwanie treści osadzonych z różnych powiązanych usług (filmów, dokumentów lub zasobów ograniczonych do użytkownika zalogowanego w witrynie najwyższego poziomu);
- Zaloguj się. obsługiwanie logowania w usługach powiązanych, W niektórych przypadkach może być też odpowiedni interfejs FedCM API.
- Analytics wdrażanie analiz i pomiarów ścieżek użytkowników w usługach powiązanych w celu poprawy jakości usług;
Szczegóły integracji zestawów powiązanych witryn
Interfejs Storage Access API
Interfejs Storage Access API (SAA) umożliwia umieszczonym treściom z innych domen dostęp do pamięci, do której normalnie miałyby dostęp tylko w kontekście własnej domeny.
Osadzone zasoby mogą używać metod SAA, aby sprawdzić, czy mają obecnie dostęp do pamięci masowej, i poprosić agenta użytkownika o przyznanie dostępu.
Gdy pliki cookie innych firm są blokowane, ale zestawy powiązanych witryn są włączone, Chrome automatycznie przyznaje uprawnienia w kontekstach wewnątrz zestawu powiązanych witryn, a w innych przypadkach wyświetla prośbę o zgodę. („Kontekst w ramach zestawu powiązanych witryn” to kontekst, np. element iframe, w którym umieszczona witryna i witryna najwyższego poziomu należą do tego samego zestawu powiązanych witryn).
Sprawdzanie i wysyłanie prośby o dostęp do pamięci masowej
Aby sprawdzić, czy obecnie mają dostęp do pamięci, osadzone witryny mogą użyć metody Document.hasStorageAccess().
Metoda zwraca obietnicę, która jest spełniana z wartością logiczną wskazującą, czy dokument ma już dostęp do swoich plików cookie. Obietnica zwraca też wartość true, jeśli element iframe pochodzi z tej samej domeny co ramka najwyższego poziomu.
Aby poprosić o dostęp do plików cookie w kontekście zewnętrznym, osadzone witryny mogą używać interfejsu Document.requestStorageAccess() (rSA).
Interfejs requestStorageAccess() API jest przeznaczony do wywoływania z poziomu elementu iframe.
Ten element iframe musi właśnie otrzymać interakcję użytkownika (gest użytkownika, który jest wymagany przez wszystkie przeglądarki), ale Chrome dodatkowo wymaga, aby w ciągu ostatnich 30 dni użytkownik odwiedził witrynę, do której należy ten element iframe, i wchodził w interakcję z tą witryną jako dokumentem najwyższego poziomu, a nie w elemencie iframe.
requestStorageAccess() zwraca obietnicę, która jest spełniana, jeśli dostęp do pamięci został przyznany. Jeśli dostęp zostanie z jakiegokolwiek powodu odrzucony, obietnica zostanie odrzucona z podaniem przyczyny.
requestStorageAccessFor w Chrome
Interfejs Storage Access API umożliwia witrynom umieszczonym na innych stronach proszenie o dostęp do pamięci masowej tylko w elementach <iframe>, z którymi użytkownik wszedł w interakcję.
Stanowi to wyzwanie w przypadku wdrażania interfejsu Storage Access API w witrynach najwyższego poziomu, które używają obrazów z innych witryn lub tagów skryptów wymagających plików cookie.
Aby rozwiązać ten problem, Chrome wprowadził mechanizm, który umożliwia witrynom najwyższego poziomu wysyłanie w imieniu konkretnych domen żądań dostępu do pamięci za pomocą funkcji Document.requestStorageAccessFor() (rSAFor).
document.requestStorageAccessFor('https://target.site')
Interfejs requestStorageAccessFor() API jest przeznaczony do wywoływania przez dokument najwyższego poziomu. Ten dokument musi też być ostatnio używany przez użytkownika. W przeciwieństwie do requestStorageAccess() Chrome nie sprawdza interakcji w dokumencie najwyższego poziomu w ciągu ostatnich 30 dni, ponieważ użytkownik jest już na stronie.
Sprawdzanie uprawnień dostępu do pamięci
Dostęp do niektórych funkcji przeglądarki, takich jak kamera czy lokalizacja geograficzna, zależy od uprawnień przyznanych przez użytkownika. Interfejs Permissions API umożliwia sprawdzanie stanu uprawnień dostępu do interfejsu API – czy zostały przyznane, odrzucone lub czy wymagają jakiejś formy interakcji użytkownika, np. kliknięcia promptu lub interakcji ze stroną.
Stan uprawnień możesz sprawdzać za pomocą funkcji navigator.permissions.query().
Aby sprawdzić uprawnienia dostępu do pamięci w bieżącym kontekście, musisz przekazać ciąg znaków 'storage-access':
navigator.permissions.query({name: 'storage-access'})
Aby sprawdzić uprawnienia dostępu do pamięci w przypadku określonego pochodzenia, musisz przekazać ciąg 'top-level-storage-access':
navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'})
Aby chronić integralność osadzonego źródła, ta funkcja sprawdza tylko uprawnienia przyznane przez dokument najwyższego poziomu za pomocą funkcji document.requestStorageAccessFor.
W zależności od tego, czy uprawnienie może zostać przyznane automatycznie, czy wymaga działania użytkownika, funkcja zwróci wartość prompt lub granted.
Model na klatkę
Uprawnienia rSA są przyznawane dla każdej ramki. Uprawnienia rSA i rSAFor są traktowane jako oddzielne uprawnienia.
Każda nowa ramka będzie musiała oddzielnie poprosić o dostęp do pamięci masowej, który zostanie jej automatycznie przyznany. Tylko pierwsze żądanie wymaga gestu użytkownika. Wszelkie kolejne żądania zainicjowane przez element iframe, takie jak nawigacja czy zasoby podrzędne, nie będą musiały czekać na gest użytkownika, ponieważ zostanie on przyznany na potrzeby sesji przeglądania przez pierwsze żądanie.
Odświeżenie, ponowne załadowanie lub inne odtworzenie elementu iframe będzie wymagać ponownego przesłania prośby o dostęp.
Wymagania dotyczące plików cookie
Pliki cookie muszą mieć atrybuty SameSite=None i Secure, ponieważ tylko rSA zapewnia dostęp do plików cookie, które są już oznaczone do użycia w kontekstach obejmujących wiele witryn.
Pliki cookie z atrybutem SameSite=Lax, SameSite=Strict lub bez atrybutu SameSite są przeznaczone wyłącznie do użytku własnego i nigdy nie będą udostępniane w kontekście wielu stron, niezależnie od rSA.
Bezpieczeństwo
W przypadku rSAFor żądania zasobów podrzędnych wymagają nagłówków współdzielenia zasobów między serwerami z różnych domen (CORS) lub atrybutu crossorigin w zasobach, co zapewnia wyraźną zgodę użytkownika.
Przykłady implementacji
Prośba o dostęp do pamięci z osadzonego międzyźródłowego elementu iframe
requestStorageAccess() w umieszczonym elemencie w innej witrynie.Sprawdzanie, czy masz dostęp do miejsca na dane
Aby sprawdzić, czy masz już dostęp do pamięci masowej, użyj document.hasStorageAccess().
Jeśli obietnica zostanie spełniona, możesz uzyskać dostęp do pamięci w kontekście międzywitrynowym. Jeśli zwraca wartość false, musisz poprosić o dostęp do pamięci.
document.hasStorageAccess().then((hasAccess) => {
if (hasAccess) {
// You can access storage in this context
} else {
// You have to request storage access
}
});
Prośba o dostęp do pamięci
Jeśli musisz poprosić o dostęp do pamięci, najpierw sprawdź uprawnienia dostępu do pamięcinavigator.permissions.query({name: 'storage-access'}), aby dowiedzieć się, czy wymagają one gestu użytkownika, czy można je przyznać automatycznie.
Jeśli uprawnienie ma wartość granted, możesz wywołać funkcję document.requestStorageAccess(), a powinna ona działać bez gestu użytkownika.
Jeśli stan uprawnień to prompt, musisz zainicjować wywołanie document.requestStorageAccess() po wykonaniu przez użytkownika gestu, np. kliknięciu przycisku.
Przykład:
navigator.permissions.query({name: 'storage-access'}).then(res => {
if (res.state === 'granted') {
// Permission has already been granted
// You can request storage access without any user gesture
rSA();
} else if (res.state === 'prompt') {
// Requesting storage access requires user gesture
// For example, clicking a button
const btn = document.createElement("button");
btn.textContent = "Grant access";
btn.addEventListener('click', () => {
// Request storage access
rSA();
});
document.body.appendChild(btn);
}
});
function rSA() {
if ('requestStorageAccess' in document) {
document.requestStorageAccess().then(
(res) => {
// Use storage access
},
(err) => {
// Handle errors
}
);
}
}
Kolejne prośby z ramki, nawigacji lub zasobów podrzędnych będą automatycznie miały uprawnienia dostępu do plików cookie w różnych witrynach.
hasStorageAccess() zwraca wartość „true”, a pliki cookie z innych witryn z tego samego zestawu powiązanych witryn będą wysyłane w tych żądaniach bez dodatkowych wywołań JavaScript.
Witryny najwyższego poziomu, które żądają dostępu do plików cookie w imieniu witryn z innych domen
requestStorageAccessFor() w witrynie najwyższego poziomu dla innego pochodzeniaWitryny najwyższego poziomu mogą używać zasady requestStorageAccessFor(), aby prosić o dostęp do miejsca na dane w imieniu określonych źródeł.
hasStorageAccess() sprawdza tylko, czy witryna, która ją wywołuje, ma dostęp do pamięci, więc witryna najwyższego poziomu może sprawdzić uprawnienia dla innego źródła.
Aby sprawdzić, czy użytkownikowi zostanie wyświetlony prompt lub czy dostęp do pamięci został już przyznany określonemu pochodzeniu, wywołaj funkcję navigator.permissions.query({name:
'top-level-storage-access', requestedOrigin: 'https://target.site'}).
Jeśli uprawnienie ma wartość granted, możesz wywołać funkcję document.requestStorageAccessFor('https://target.site'). Powinno się to udać bez interakcji użytkownika.
Jeśli uprawnienie ma wartość prompt, wywołanie funkcji document.requestStorageAccessFor('https://target.site') musi być powiązane z gestem użytkownika, np. kliknięciem przycisku.
Przykład:
navigator.permissions.query({name:'top-level-storage-access',requestedOrigin: 'https://target.site'}).then(res => {
if (res.state === 'granted') {
// Permission has already been granted
// You can request storage access without any user gesture
rSAFor();
} else if (res.state === 'prompt') {
// Requesting storage access requires user gesture
// For example, clicking a button
const btn = document.createElement("button");
btn.textContent = "Grant access";
btn.addEventListener('click', () => {
// Request storage access
rSAFor();
});
document.body.appendChild(btn);
}
});
function rSAFor() {
if ('requestStorageAccessFor' in document) {
document.requestStorageAccessFor().then(
(res) => {
// Use storage access
},
(err) => {
// Handle errors
}
);
}
}
Po udanym wywołaniu funkcji requestStorageAccessFor() żądania z innych witryn będą zawierać pliki cookie, jeśli zawierają CORS lub atrybut crossorigin, więc witryny mogą poczekać przed wywołaniem żądania.
Żądania muszą korzystać z opcji credentials: 'include', a zasoby muszą zawierać atrybut crossorigin="use-credentials".
function checkCookie() {
fetch('https://related-website-sets.glitch.me/getcookies.json', {
method: 'GET',
credentials: 'include'
})
.then((response) => response.json())
.then((json) => {
// Do something
});
}
Jak testować lokalnie
Wymagania wstępne
Aby lokalnie przetestować zestawy powiązanych witryn, użyj Chrome 119 lub nowszej wersji uruchomionej z wiersza poleceń i włącz test-third-party-cookie-phaseout flagę Chrome.
Włączanie flagi Chrome
Aby włączyć odpowiednią flagę Chrome, otwórz chrome://flags#test-third-party-cookie-phaseout na pasku adresu i zmień ustawienie flagi na Enabled. Po zmianie flag uruchom ponownie przeglądarkę.
Uruchamianie Chrome z lokalnym zestawem powiązanych witryn
Aby uruchomić Chrome z lokalnie zadeklarowanym zestawem powiązanych witryn, utwórz obiekt JSON zawierający adresy URL należące do zestawu i przekaż go do --use-related-website-set.
Dowiedz się więcej o uruchamianiu Chromium z flagami.
--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/
Przykład
Aby włączyć lokalnie powiązane zbiory witryn, musisz włączyć test-third-party-cookie-phaseout w chrome://flags i uruchomić Chrome z wiersza poleceń za pomocą flagi --use-related-website-set z obiektem JSON zawierającym adresy URL należące do zbioru.
--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/
Sprawdź, czy masz dostęp do plików cookie innych witryn.
Wywołaj interfejsy API (rSA lub rSAFor) z testowanych witryn i sprawdź dostęp do plików cookie innych witryn.
Proces przesyłania zestawów powiązanych witryn
Aby zadeklarować relację między domenami i określić, do której podgrupy należą, wykonaj te czynności.
1. Identyfikowanie RWS
Określ odpowiednie domeny, w tym ustaw witrynę główną i ustaw witryny członkowskie, które będą częścią zestawu powiązanych witryn. Określ też, do którego typu podzbioru należy każdy element zbioru.
2. Tworzenie zgłoszenia RWS
Utwórz lokalną kopię (klon lub rozwidlenie) repozytorium GitHub. W nowej gałęzi wprowadź zmiany w pliku related_website_sets.JSON, aby odzwierciedlały Twój zestaw. Aby mieć pewność, że zestaw ma prawidłowy format i strukturę JSON, możesz użyć narzędzia do generowania kodu JSON.
3. Sprawdź, czy RWS spełnia wymagania techniczne
Sprawdź, czy spełniasz wymagania dotyczące tworzenia zestawów i wymagania dotyczące weryfikacji zestawów.
4. Lokalne testowanie RWS
Przed utworzeniem prośby o scalenie w celu przesłania zestawu przetestuj przesłany plik lokalnie, aby upewnić się, że przejdzie wszystkie wymagane testy.
5. Przesyłanie RWS
Prześlij zestaw powiązanych witryn, tworząc żądanie pull request do pliku related_website_sets.JSON, w którym Chrome przechowuje kanoniczną listę zestawów powiązanych witryn. (Do tworzenia żądań pull request wymagane jest konto GitHub. Zanim zaczniesz dodawać treści do listy, musisz podpisać umowę licencyjną dla współtwórców).
Po utworzeniu żądania scalenia przeprowadzana jest seria testów, aby upewnić się, że spełnione są wymagania z kroku 3, np. czy podpisano umowę CLA i czy plik .well-known jest prawidłowy.
Jeśli się uda, w żądaniu pull request pojawi się informacja, że weryfikacja została zakończona. Zatwierdzone żądania scalania będą ręcznie scalane w partiach z kanoniczną listą zestawów powiązanych witryn raz w tygodniu (we wtorki o godzinie 12:00 czasu wschodniego). Jeśli któryś z testów zakończy się niepowodzeniem, osoba przesyłająca otrzyma powiadomienie o niepowodzeniu żądania pull request w GitHubie. Osoba przesyłająca może poprawić błędy i zaktualizować prośbę o scalenie. Należy pamiętać, że:
- Jeśli żądanie PR się nie powiedzie, w komunikacie o błędzie znajdziesz dodatkowe informacje o przyczynie niepowodzenia. (przykład).
- Wszystkie kontrole techniczne dotyczące przesłanych zestawów są przeprowadzane w GitHubie, dlatego wszystkie błędy przesłania wynikające z kontroli technicznych będą widoczne w GitHubie.
Zasady firmowe
Chrome ma 2 zasady, które zaspokajają potrzeby użytkowników biznesowych:
- Systemy, które mogą nie być w stanie zintegrować się z zestawami powiązanych witryn, mogą wyłączyć tę funkcję we wszystkich instancjach Chrome dla przedsiębiorstw za pomocą zasady
RelatedWebsiteSetsEnabled.- Niektóre systemy korporacyjne mają witryny dostępne tylko w sieci wewnętrznej (np. intranet) z domenami, które można zarejestrować i które różnią się od domen w zestawie powiązanych witryn. Jeśli chcą traktować te witryny jako część zestawu powiązanych witryn bez ujawniania ich publicznie (ponieważ domeny mogą być poufne), mogą rozszerzyć lub zastąpić publiczną listę zestawów powiązanych witryn za pomocą
RelatedWebsiteSetsOverrideszasady.
- Niektóre systemy korporacyjne mają witryny dostępne tylko w sieci wewnętrznej (np. intranet) z domenami, które można zarejestrować i które różnią się od domen w zestawie powiązanych witryn. Jeśli chcą traktować te witryny jako część zestawu powiązanych witryn bez ujawniania ich publicznie (ponieważ domeny mogą być poufne), mogą rozszerzyć lub zastąpić publiczną listę zestawów powiązanych witryn za pomocą
Chrome rozwiązuje wszelkie przecięcia zbiorów publicznych i firmowych na 2 sposoby, w zależności od tego, czy określono replacements czy additions.
Na przykład w przypadku zbioru publicznego {primary: A, associated: [B, C]}:
replacements seta: |
{primary: C, associated: [D, E]} |
| Zestaw Enterprise wchłania wspólną witrynę, tworząc nowy zestaw. | |
| Otrzymane zbiory: | {primary: A, associated: [B]}{primary: C, associated: [D, E]} |
additions seta: |
{primary: C, associated: [D, E]} |
| Zestawy Public i Enterprise są połączone. | |
| Otrzymany zbiór: | {primary: C, associated: [A, B, D, E]} |
Rozwiązywanie problemów z zestawami powiązanych witryn
„Prompt użytkownika” i „gest użytkownika”
„Prompt użytkownika” i „gest użytkownika” to różne pojęcia. Chrome nie wyświetla użytkownikom prośby o uprawnienia w przypadku witryn należących do tego samego zestawu powiązanych witryn, ale nadal wymaga, aby użytkownik wchodził w interakcję ze stroną. Przed przyznaniem uprawnień Chrome wymaga gestu użytkownika, zwanego też „interakcją użytkownika” lub „aktywacją użytkownika”. Dzieje się tak, ponieważ korzystanie z interfejsu Storage Access API poza kontekstem zestawu powiązanych witryn (czyli requestStorageAccess()) również wymaga gestu użytkownika ze względu na zasady projektowania platformy internetowej.
Dostęp do plików cookie lub pamięci innych witryn
Zestawy powiązanych witryn nie łączą pamięci różnych witryn, tylko ułatwiają (bez wyświetlania prośby) wywoływanie requestStorageAccess(). Zestawy powiązanych witryn tylko zmniejszają trudności użytkownika związane z korzystaniem z interfejsu Storage Access API, ale nie określają, co należy zrobić po przywróceniu dostępu. Jeśli A i B to różne witryny w tym samym zestawie powiązanych witryn, a A osadza B, witryna B może wywołać requestStorageAccess()
i uzyskać dostęp do pamięci własnej bez wyświetlania użytkownikowi prośby o zgodę. Zestawy powiązanych witryn nie prowadzą komunikacji między witrynami. Na przykład skonfigurowanie zestawu powiązanych witryn nie spowoduje, że pliki cookie należące do witryny B zaczną być wysyłane do witryny A. Jeśli chcesz udostępnić te dane, musisz to zrobić samodzielnie, np. wysyłając window.postMessage z ramki B do ramki A.
Domyślny dostęp do niepodzielonych plików cookie
Zestawy powiązanych witryn nie zezwalają na niejawny dostęp do plików cookie bez partycji bez wywoływania żadnego interfejsu API. Pliki cookie z wielu witryn nie są domyślnie udostępniane w ramach zestawu. Zestawy powiązanych witryn umożliwiają tylko witrynom w zestawie pomijanie prośby o zezwolenie na dostęp do pamięci przez interfejs Storage Access API.
Jeśli element iframe chce uzyskać dostęp do swoich plików cookie, musi wywołać funkcję document.requestStorageAccess(). Strona najwyższego poziomu może wywołać funkcję document.requestStorageAccessFor().
Podziel się opinią
Przesyłanie zestawu na GitHubie i korzystanie z interfejsu Storage Access API oraz interfejsu requestStorageAccessFor API to okazja do podzielenia się swoimi doświadczeniami z tym procesem i wszelkimi napotkanymi problemami.
Aby dołączyć do dyskusji o zestawach powiązanych witryn:
- Dołącz do publicznej listy mailingowej dotyczącej zestawów powiązanych witryn.
- Zgłaszaj problemy i śledź dyskusję w repozytorium GitHub dotyczącym powiązanych zestawów witryn.