# Advanced Take advantage of advanced capabilities of the Airship Web SDK. # Localization > Override the user's default locale to utilize localization for a specific language.See [Localization](https://www.airship.com/docs/guides/messaging/messages/localization/) in our message content documentation for more details. ## Overriding locale Airship uses the user's [Locale](https://www.airship.com/docs/reference/glossary/#locale) for various locale-sensitive tasks, including selecting the language for messages and reporting for analytics. The SDK can override the locale so that Airship uses a different locale than the browser's current locale. In the Web SDK, a locale can be set before or after creating a channel. If set, it overrides the browser's locale information. See the Web SDK reference for the full [Locale Manager](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/LocaleManager.html) . **Setting the locale language:** ```js const sdk = await UA await sdk.locale.set({language: 'fr'}) ``` **Setting the locale country:** ```js const sdk = await UA await sdk.locale.set({country: 'FR'}) ``` **Clear the locale override:** ```js const sdk = await UA await sdk.locale.clear() ``` **Setting/replacing locale:** ```js const sdk = await UA // replace just the language await sdk.locale.set({language :'fr'}) // replace just the country await sdk.locale.set({country :'FR'}) // replace both await sdk.locale.set({country :'fr', language :'fr'}) ``` Overrides can be reset by passing `null` as the value for either the `country` or `language` key to `set()`. **Resetting locale:** ```js const sdk = await UA await sdk.locale.set({country: null, language: 'fr'}) ``` You may also retrieve the current resolved locale; this will coalesce the values provided by the browser with the current override values that you have set: **Getting the current locale settings:** ```js const sdk = await UA const {language, country} = await sdk.locale.get() ``` > **Note:** Not all browser and OS combinations will provide a country, so the value of `country` may be `null`. # Tag Manager Integrations > Deploy web push notifications on your site using third-party tag managers.## Supported Tag Managers Our web push SDK can be deployed via Google Tag Manager (GTM), Ensighten, and Tealium. For GTM integrations, you will use the *Custom HTML* tag type; instructions are provided below. For Ensighten and Tealium, select the Airship tag option in the respective tag manager UI when setting up web push notifications. ## Google Tag Manager The Airship Web SDK can be implemented using [Google Tag Manager](https://www.google.com/analytics/tag-manager/). This section assumes that you have already completed the following steps at the beginning of this guide: 1. [Airship Setup](https://www.airship.com/docs/developer/sdk-integration/web/getting-started/#airship-setup) 1. [Add push-worker.js to your root directory](https://www.airship.com/docs/developer/sdk-integration/web/getting-started/#place-service-worker) > **Important:** The push worker must be placed at the root of the server. Its function is to > create and sustain what is called a > [service worker](https://developers.google.com/web/fundamentals/primers/service-workers/), > which provides a safe and secure way to interact with a site as a background > task. These files cannot be managed within the Google Tag Manager environment, > as they live at a level above HTML content and must be directly accessible > rather than imported into a page. The remaining steps are handled through the Google Tag Manager interface. ### Install Google Tag Manager 1. In [Google Tag Manager](https://tagmanager.google.com), select your container, click **Admin** in the navigational header, then click **Install Google Tag Manager**. 1. Follow Google's instructions to add Google Tag Manager to any HTTPS-delivered page. ### Configure Your Web Push Tag Next, we will configure a new tag in your newly-created Google Tag Manager container, using the Custom HTML tag type. 1. Click **Workspace** in the navigational header, then click the *New Tag* pane. 1. Enter "Web Push" in the title field, then click the *Tag Configuration* pane. 1. Click the tag type *Custom HTML*, then paste the code at the end of this section into the HTML field. * Replace all bracketed values in the provided GTM code, e.g., ``, with the corresponding values for your site. You can find them in your `push-worker.js` file. * **Do not check the box** for *Support document.write* **Configure Web Push Tag** ```html ``` ### Choose a Trigger > **Important:** When triggered, the above tag will register a channel for the visitor. This will > be counted toward your [Monthly Unique Visitors](https://www.airship.com/docs/reference/billing/#monthly-unique-visitors). You may wish to restrict > triggering such that you only register channels when a user has become relevant > for your use case. 1. Click the *Triggering* pane, then click the row for *All Pages*. You can edit this later, if desired. 1. Click the **Save** button, and you will be returned to the Workspace. 1. Click the **Submit** button. 1. Enter a Version name and description for this submission's changes, then click the **Publish** button. 1. Test to see if notifications are working, using the provided **Sign up for notifications** button code. **Example to provide a button to test GTM implementation** ```html

Web Push Test Page

``` # Preference Center > Implement a preference center on your website.> **Important:** Airship Preference Centers are widgets that can be embedded in a page in an app or website. Please verify with your legal team that your full Preference Center page, including any web page for email Preference Centers, is compliant with local privacy regulations. A preference center consists of these interfaces: * [PreferenceCenterManager](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/PreferenceCenterManager.html) — Provides an interface for fetching preference center definitions. * [PreferenceCenter](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/global.html#PreferenceCenter) — A data structure that defines a preference center in a format that is convenient for rendering in your toolkit of choice. * [Channel](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/UaSDK.Channel.html) — Can be opted in or out of subscription lists. * [Contact](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/UaSDK.Contact.html) — Can be opted in or out of scoped subscription lists. * [SubscriptionListManager](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/SubscriptionListManager.html) — An interface for managing a channel's subscription list membership. * [ScopedSubscriptionListManager](https://www.airship.com/docs/reference/libraries/web-notify-sdk/v2-latest/ScopedSubscriptionListManager.html) — An interface for managing a contact's scoped subscription list membership. When implementing a preference center, you will fetch the preference center's definition, render it in your chosen toolkit, and listen for the end user's interactions with the various subscription list items to manage the channel's or contact's opting in or out of a list. Preference centers are referred to by `id`, and you may have multiple preference centers within your app. * The `await channel.subscriptions.list()` returns an array of subscription list ids type: `string[]`. * The `await contact.subscriptions.list()` returns a `ScopedSubscriptionListIdentifier` of type `{[key: string]: Scope[]}`, where the key is the subscription list id, e.g., `{listId1: ['app', 'web'], listId2: ['email']}`. ## Web SDK Preference Center Examples > **Note:** How you implement a preference center will depend heavily on your UI toolkit of choice. The following examples purposefully ignore those details. **Example for a Channel preference center implementation** ```js const sdk = await UA const id = "my_preference_center" // refers to the ID you created in the Airship Dashboard // retrieve the preference center by id const preferenceCenterDefinition = await sdk.components.preferenceCenters.get(id) // render your preference center component; here we assume some class // `PreferenceUi` which takes a definition and returns an event // emitter which emits membership changes based on end-user interactions, but // this will be up to your implementation. const preferenceUi = new PreferenceUi(preferenceCenterDefinition) preferenceUi.addEventListener("list_change", async (e) => { const { operation, // assume string "subscribe" or "unsubscribe" listId, // the id of the list } = e.detail // now that you have received an event, use the Airship SDK to alter the // channels list membership const editor = await sdk.channel.subscriptions.edit() // subscribe or unsubscribe, depending on the operation if (operation === "subscribe") { editor.subscribe(listId) } else if (operation === "unsubscribe") { editor.unsubscribe(listId) } // apply the changes await editor.apply() }) ``` **Example for a Contact preference center implementation** ```js const sdk = await UA const id = "my_cross_channel_preference_center" // refers to the ID you created in the Airship Dashboard // retrieve the preference center by id const preferenceCenterDefinition = await sdk.components.preferenceCenters.get(id) // render your preference center component; here we assume some class // `PreferenceUi` which takes a definition and returns an event // emitter which emits membership changes based on end-user interactions, but // this will be up to your implementation. const preferenceUi = new PreferenceUi(preferenceCenterDefinition) preferenceUi.addEventListener("list_change", async (e) => { const { operation, // assume string "subscribe" or "unsubscribe" listId, // the id of the list scope, // the scope to which you are subscribing or unsubscribing (e.g. "web") } = e.detail // If this is not a scoped (i.e. contact-level) operation, // it cannot be handled by the contact subscription manager if (!scope) return // now that you have received an event, use the Airship SDK to alter the // contact list membership const contact = await sdk.contact const editor = await contact.subscriptions.edit() // subscribe or unsubscribe, depending on the operation if (operation === "subscribe") { editor.subscribe(listId, scope) } else if (operation === "unsubscribe") { editor.unsubscribe(listId, scope) } // apply the changes await editor.apply() }) ```