# Tools & Features Learn about dashboard tools and individual features, like Preference Centers and Feature Flags. # Setting brand guidelines > Ensure consistent brand identity by defining a profile, design elements, and personalities. Design elements automatically apply to specific message types, and you can also select them when creating messages. The profile and personalities are combined to create content for AI-generated Journeys. Users with [Owner, Administrator, or Full Access permission](https://www.airship.com/docs/guides/getting-started/admin/teams-messaging/#access-levels) can set brand guidelines. ## Brand guidelines definitions and use The guidelines you set are used for various purposes in Airship: | Guideline | Description | Use | | --- | --- | --- | | **Profile and personalities** | Your profile defines your brand's mission, vision, positioning, and values. Each personality should be for a distinct tone, such as enthusiastic, rugged, sincere, or excited. | When creating AI-generated [Journeys](https://www.airship.com/docs/reference/glossary/#journey), your brand profile and a selected personality are used by Generative AI to create message content.

See [Create AI-generated Journeys](https://www.airship.com/docs/guides/features/orchestration-experimentation/journeys/#create-ai-generated-journeys). | | **Colors and fonts** | Each color is defined as a [Color Set](https://www.airship.com/docs/reference/glossary/#color_set). Custom fonts are rendered in [In-App Automations](https://www.airship.com/docs/reference/glossary/#iaa) and [Scenes](https://www.airship.com/docs/reference/glossary/#scene) according to a font stack, which is a list of the names of individual fonts available in your app. | Select color sets and font stacks when configuring the default appearance of In-App Automations and Scenes and when creating individual messages.

See [In-app experience defaults](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/), [Create a Scene](https://www.airship.com/docs/guides/messaging/in-app-experiences/scenes/create/), and [Create an In-App Automation](https://www.airship.com/docs/guides/messaging/in-app-experiences/in-app-automation/create/). | | **Text, button, and input field styles** | Styles are collections of settings that determine the appearance of [Scene](https://www.airship.com/docs/reference/glossary/#scene) content. Selecting a style applies all its settings at once. | Select styles when configuring the default appearance of Scenes and when creating individual messages.

See [In-app experience defaults](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/) and [Create a Scene](https://www.airship.com/docs/guides/messaging/in-app-experiences/scenes/create/). | {class="table-col-1-30"} ## Methods and Generative AI You can set all brand guidelines manually. You also have the option to provide source material and let Airship derive and set your guidelines using Generative AI: * For your profile and design elements, upload PDFs outlining the language, colors, fonts, and other design elements to use in your messages, and select which guidelines to apply them to. These are documents that represent your brand, such as your company's "Style Guide" or "Brand Guidelines." You can upload multiple sources for different guidelines or to overwrite previous values. See [Set brand guidelines from uploaded sources](#set-brand-guidelines-from-uploaded-sources). * For your personalities, directly enter writing samples or upload PDFs of samples. You can add multiple writing samples for each personality. See [Set personalities](#set-personalities). > **Note:** **Opting In to AI Functions** > > If you opted out of AI usage, you must sign an updated contract to enable this feature. Contact your account manager for assistance. > > **Compliance Considerations in Using AI Functions** > > The Service incorporates AI functions, including Generative AI and Agentic AI. > > Generative AI generates content such as Notification copy, images, and Journeys based on your prompts. > > Agentic AI autonomously optimizes, personalizes, or executes cross-channel customer engagement actions, or analyzes audience and performance data, subject to the parameters and controls you set in the Service. These systems operate under human-defined parameters and do not initiate customer-facing actions without human interaction or pre-configured parameters. You are responsible for reviewing Generated Outputs for accuracy, appropriateness, and to ensure they do not violate third-party intellectual property or other rights. Airship does not publish Generated Outputs to end users without approval from the Customer. > > In addition to the applicable terms of your agreement with Airship (e.g., Use of Service, Customer Responsibilities sections), you must comply with the [Airship Acceptable Use Policy](https://www.airship.com/legal/acceptable-use/), which provides additional details about appropriate conduct when using the Service. > > The Service includes safety features to block harmful content, such as content that violates our Acceptable Use Policy. You may not attempt to bypass these protective measures or use content that violates your agreement with Airship. > > About the AI models: > > Airship utilizes Google Gemini and Imagen to generate copy and images for AI Scene screens. The content is created solely with Google's out-of-the-box models, and no customization or fine-tuning with Customer Data is applied. See [Responsible AI](https://cloud.google.com/responsible-ai?hl=en) in Google's *Google Cloud* documentation. ## Set brand guidelines manually For personalities, see [Set personalities](#set-personalities) below. For all other guidelines, use the following steps. ### Profile Your profile defines fundamental aspects of your brand identity and the core values that guide your brand. When creating an AI-generated [Journey](https://www.airship.com/docs/reference/glossary/#journey), its content is created based on the current version of your brand profile and a specified personality. To manually manage your brand profile: 1. Next to your project name, select the dropdown menu (▼), then **Brand Guidelines**. 1. Under **Brand**, select **Profile**. 1. Select **Edit** and enter text for each field: | Field | Description | | --- | --- | | **Vision** | Your brand's vision for the future | | **Mission** | Your brand's mission and purpose | | **Positioning** | How you want your brand to be perceived | 1. Select **Add value** and enter a name for the value and how it manifests in your brand. Repeat for additional values. 1. Select **Save**. ### Colors Colors are defined as color sets. A *Color Set* is a named pair of hexadecimal color values supporting device Light and Dark modes. Color sets can be selected for any color field in a Scene and when configuring the default appearance of Scenes and In-App Automations. Dark mode is supported for Scenes only. When you edit a color set, the changes automatically update anywhere the set is in use. You may want to update your color sets seasonally or when refreshing your branding. New projects have 10 preset color sets. > **Note:** Color sets used in [In-App Automation defaults](#setting-in-app-automation-defaults) appear as their Light Mode hexadecimal color values, not the color set name, in In-App Automation composer color fields. They appear as their color set name in [Scene defaults](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/#scene-defaults) and in the Scene composer. To manually add color sets: 1. Next to your project name, select the dropdown menu (▼), then **Brand Guidelines**. 1. Under **Elements**, select **Colors**. 1. Select **Add color set** and enter a name for the color set, Light and Dark Mode hexadecimal color values, and opacity percentages. Repeat for additional sets. 1. Select **Save**. Options for existing color sets: | Option | Description | Steps | | --- | --- | --- | | **Edit** | You can change any part of the configuration. | Select the more menu icon (⋯) for a color set, then **Edit colors**, edit the settings, then select **Save**. | | **Duplicate** | Make a copy of the color set. | Select the more menu icon (⋯) for a color set, then **Duplicate**. | | **Delete** | Remove the color set from your project. | Select the more menu icon (⋯) for a color set, then **Edit colors**, then **Delete**. | > **Important:** If editing or deleting a color set that is in use, make sure to update the values for the affected fields in your in-app experiences and your [In-App Automation defaults](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/#setting-in-app-automation-defaults) and [Scene defaults](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/#scene-defaults). ### Fonts When configuring the content of your in-app experiences, or when setting their defaults, you must set a font size and font family for text. For font size, see [Fonts](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/#fonts) in *In-app experience default settings*. The remainder of this section is about font families. All Airship projects contain a serif and sans-serif font. You can also add custom fonts in your brand guidelines so your in-app experiences use the same fonts as the rest of your app. Custom fonts are rendered in your messages according to a font stack, which is a list of the names of individual fonts available in your app. **Guidelines for font stacks:** * Create separate stacks for serif and sans-serif fonts. * Each font name should match the fonts that are in your app. * Your Primary Font should be the font you want to appear in your messages by default. You can also provide a web font URL for the Primary Font so it can be rendered in device previews when creating and editing Scenes. * Add Fallback Fonts to be used by your app if the Primary Font doesn't load. They will be loaded in the order they are listed in the stack. * If your project supports both iOS and Android, your Primary Font and first Fallback Font should collectively serve as the default fonts for both platforms. For instance, if iOS uses `MyFont` and Android uses `myfont`, assign one as the Primary Font and the other as the first Fallback Font. After creating a custom font stack, you can select it as a font family when configuring appearance defaults and text and button fields in In-App Automations and Scenes. Since font name format varies between iOS and Android, custom font stacks also allow font names to be unified into a single selection. > **Important:** Confirm your app's font names with your developer before creating custom font stacks. > > 1. Adding custom fonts in your project settings does not add the font to your app. A developer must add the font to your app. See our platform documentation for customizing in-app experiences: > * [iOS: Fonts](https://www.airship.com/docs/developer/sdk-integration/apple/in-app-experiences/in-app-automation/#fonts) > * [Android: Fonts](https://www.airship.com/docs/developer/sdk-integration/android/in-app-experiences/in-app-automation/#fonts) > > 1. The font names you enter when creating a font stack must match the names as configured in your app, keeping in mind that font name format varies by app platform: > | Option | Steps | > | --- | --- | > | **Android** | Use the name that is in your app's fonts.xml. See the [Fonts In XML guide](https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html). For example, if you define a font in res/fonts/my_cool_font.xml, the font name is my_cool_font. | > | **iOS** | Use the font family name, including spaces. For example, `Roboto Condensed`. This is not necessarily the filename of the font. One way to verify the family name is to check the Identifiers section for the font in the Font Book application on macOS. | To manually add a font stack: 1. Next to your project name, select the dropdown menu (▼), then **Brand Guidelines**. 1. Under **Elements**, select **Fonts**. 1. Select **Add font stack**. 1. Enter a name for the stack and select whether it is for serif or sans-serif fonts. 1. For **Primary Font**, enter the name for the primary font and an optional publicly accessible web font URL.

The font URL is used for rendering the font in previews when creating and editing Scenes. It must be for either a file or a web font service such as Google Fonts. Supported file types: WOFF, WOFF2, TTF, EOT. Example web font service CSS URL: `https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@200`.

1. Under **Fallback Fonts**, select **Add fallback** and enter a font name. Repeat for additional fonts. 1. Select **Save**. Options for existing font stacks: | Option | Description | Steps | | --- | --- | --- | | **Edit** | You can change any part of the configuration. | Select the more menu icon (⋯) for a font stack, then **Edit**, edit the settings, then select **Save**. | | **Delete** | Remove the font stack from your project. | Select the more menu icon (⋯) for a stack, then **Edit**, then **Delete**. | ### Text, button, and input styles

The styles for text, button, and input fields can be selected when configuring other default settings and when creating Scene content. Input styles control the appearance of the user input fields for the Email, SMS, Text Input, and Open Question content elements.

Each project supports up to 25 of each style. There are preset styles you can edit or remove. To manually add a text, button, or input style: 1. Next to your project name, select the dropdown menu (▼), then **Brand Guidelines**. 1. Under **Elements**, select **Text**, **Buttons**, or **Inputs**. 1. Select **Add text/button/input style** and configure each field. A preview of the style updates as you make changes: Text fields: | Field | Description | Steps | | --- | --- | --- | | **Name** | A descriptive name for the style. The name appears in the list of all text styles when configuring button styles and [configuring Scene content](https://www.airship.com/docs/guides/messaging/editors/native/about/). | Enter text. | | **Font** | The font of the text: serif, sans-serif, or a [custom font stack](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/#custom-fonts). | Select a font or font stack. | | **Font size** | The size of the font in points. | Enter a numeric value. | | **Font weight** | The thickness of the font, from 100 to 900. Common values are 300 for light, 400 for normal, and 700 for bold. Available weights depend on the selected font family. For SDK versions older than the required minimums, weights 100–600 fall back to 400 (normal), and weights 700–900 fall back to 700 (bold). [iOS SDK 20.1+](/docs/docs/developer/sdk-integration/apple/ios-changelog/#20.1.0) [Android SDK 20.1+](/docs/docs/developer/sdk-integration/android/changelog/#20.1.0) | Enter a numeric value. | | **Line height** | The vertical spacing between lines of text, as a multiplier. For example, 1.2 is 120% of the font size. [iOS SDK 20.1+](/docs/docs/developer/sdk-integration/apple/ios-changelog/#20.1.0) [Android SDK 20.1+](/docs/docs/developer/sdk-integration/android/changelog/#20.1.0) | Enter a numeric value. | | **Letter spacing** | The horizontal spacing between characters, in points. [iOS SDK 20.1+](/docs/docs/developer/sdk-integration/apple/ios-changelog/#20.1.0) [Android SDK 20.1+](/docs/docs/developer/sdk-integration/android/changelog/#20.1.0) | Enter a numeric value. | | **Alignment** | The horizontal position of the text: left, middle, or right. | Select an alignment. | | **Emphasis** | The format of the text: bold, italic, or underline. | Select an emphasis. | | **Color** | The color of the text. | Select a [color set](#colors). | | **Accessibility heading level** | Optional, applies to [Text](https://www.airship.com/docs/guides/messaging/editors/native/elements/#text) elements in Scenes only. The heading level of the text, for navigation using assistive technology such as screen readers. [iOS SDK 18.13+](/docs/docs/developer/sdk-integration/apple/ios-changelog/#18.13.0) [Android SDK 18.5+](/docs/docs/developer/sdk-integration/android/changelog/#18.5.0) | Select from H1 to H6. | Button fields: | Field | Description | Steps | | --- | --- | --- | | **Name** | A descriptive name for the style. The name appears in the list of all button styles when [configuring Scene content](https://www.airship.com/docs/guides/messaging/editors/native/about/). | Enter text. | | **Text style** | The format of the text, defined by a text style. | Select a text style. | | **Background color** | The color of the button background. | Select a [color set](#colors). | | **Border color** | The color of the button border. | Select a [color set](#colors). | | **Border width** | The size of the button border in pixels. | Enter a numeric value. | | **Border radius** | Governs rounding the button corners. | Enter an integer from 0 to 100. | Input fields: | Field | Description | Steps | | --- | --- | --- | | **Name** | A descriptive name for the style. The name appears in the list of all input styles when configuring the [Email](https://www.airship.com/docs/guides/messaging/editors/native/elements/#email), [SMS](https://www.airship.com/docs/guides/messaging/editors/native/elements/#sms), [Text Input](https://www.airship.com/docs/guides/messaging/editors/native/elements/#text-input), and [Open Question](https://www.airship.com/docs/guides/messaging/editors/native/elements/#question) elements in a Scene. | Enter text. | | **Text style** | The format of the text typed in the field by the user, defined by a text style. | Select a text style. | | **Background color** | The color of the input field background. | Select a [color set](#colors). | | **Placeholder color** | The color of the input field placeholder text. | Select a [color set](#colors). | | **Border color** | The color of the input field border. | Select a [color set](#colors). | | **Border width** | The size of the input field border in pixels. | Enter a numeric value. | | **Border radius** | Governs rounding the input field corners. | Enter an integer from 0 to 100. | 1. Select **Save**. Options for existing styles: | Option | Description | Steps | | --- | --- | --- | | **Edit** | Change any part of the configuration. | Select the more menu icon (⋯) for a style, then **Edit style**, edit the settings, then select **Save**. | | **Duplicate** | Make a copy of the style. | Select the more menu icon (⋯) for a style, then **Duplicate**. | | **Delete** | Remove the style from your project. | Select the more menu icon (⋯) for a color set, then **Edit style**, then **Delete**. | ## Set brand guidelines from uploaded sources [AXP](https://www.airship.com/docs/reference/feature-packages/) [Generative AI](https://www.airship.com/docs/guides/features/intelligence-ai/ai/) For all guidelines except personalities, you will first upload at least one PDF and specify which guidelines its content should apply to. Airship will analyze the content, apply values, and flag changed guidelines for review. You can then review each flagged item and apply or reject the changes. Upload your source material: ![Brand guidelines flagged for review](https://www.airship.com/docs/images/brand-guidelines-flagged_hu_b39624e83c225248.webp) *Brand guidelines flagged for review* 1. Next to your project name, select the dropdown menu (▼), then **Brand Guidelines**. 1. Under **Brand**, select **Sources**. 1. Select **+ Add source**, then **Choose files**, and choose at least one PDF. 1. Select one or more guidelines to apply the source material to. 1. Select **Upload attachments**. After processing the upload, a review icon (eye) appears in the sidebar for any changed guideline. The number of items to review appears next to the icon. If items were also added, the number of added items appears next to an add icon (+). Review your changes and additions: 1. Select a guideline for review. 1. For changes, select **eye Review updates** and review the initial and changed values, then select **Reject all changes** to discard or **Accept all changes** to apply the new values. 1. For additions, select **Reject** or **Accept**. If you edit and save a color before accepting or rejecting, the options will be replaced with **eye Review updates**. To view a record of uploads, under **Brand**, select **Sources**. Each file is listed by name and which guidelines were selected for application. To delete a source, select the more menu icon (⋯), then **Delete**. Deleting removes the file from the list only. It does not affect your current guidelines. ## Set personalities [AXP](https://www.airship.com/docs/reference/feature-packages/) [Generative AI](https://www.airship.com/docs/guides/features/intelligence-ai/ai/) For personalities, add your own tonal attributes or let Airship create them based on the writing samples you provide. Explicit content is excluded by Airship, and you can also specify your own list of banned words and phrases. When creating an AI-generated [Journey](https://www.airship.com/docs/reference/glossary/#journey), its content is created based on the current version of your brand profile and a specified personality. Add a personality: 1. Next to your project name, select the dropdown menu (▼), then **Brand Guidelines**. 1. Select the plus sign icon (+) for **Personalities**. 1. Enter a name for the personality. 1. (To manually add attributes) Under **Tonal Attribute**, select **Add attribute** and enter an adjective and description. Repeat for additional attributes. 1. (To add attributes based on writing sample) Under **Writing Samples**, enter sample text and/or select **Choose files** and choose at least one PDF. 1. Under **Forbidden Words/Phrases**, enter any words or phrases to exclude from generated content. 1. Select **Save changes**. After adding tonal attributes, you can manually edit them or use AI to generate new ones. Whenever you add a writing sample, Airship generates new attributes that replace the current ones. We recommend verifying that generated content matches your personality settings and excludes forbidden words or phrases you've set. Options for existing personalities: | Option | Description | Steps | | --- | --- | --- | | **Edit personality name** | Change the name as it appears in Brand Guidelines and when creating an AI-generated Journey. | Select **Edit**, enter a new name, then select **Save changes**. | | **Manually edit or delete tonal attributes** | Change the information available for creating content in AI-generated Journeys. | Select **Edit**, change the adjective and/or description for an attribute, select the delete icon (×) to delete an attribute, then select **Save changes**. | | **Add writing samples** | Airship will generate new tonal attributes based on all writing samples for the personality, replacing the current attributes. | Select **Edit**, enter sample text and/or select **Choose files** and choose at least one PDF, then select **Save changes**. | | **Delete writing samples** | The sample will be removed from the list, but Airship will not generate new tonal attributes unless you apply the change. | Under **Writing Samples** select the more menu icon (⋯) for a sample, then **Delete**. To also generate new tonal attributes, select **Edit**, then **Save Changes**. | | **Delete a personality** | Remove the personality from your brand guidelines. Its writing samples will also be deleted, and the personality will no longer be an option when creating AI-generated Journeys. | Select **Edit**, then **Delete**. | # Campaigns > Keep your project organized by grouping related messages into Campaigns. ## About Campaigns Campaigns present your selected messages in list and calendar views, giving you: * **Focused hubs** — Keep all messaging for a product launch, seasonal promotion, or event in one place. * **Cross-channel visibility** — Get a complete picture of your coordinated marketing effort. * **Scheduling and monitoring tools** — Use the calendar to spot scheduling gaps, avoid overlap, and optimize timing. You can sort and filter in both the list and calendar views to track status. Open messages for editing, access reports, and create new messages directly from the Campaign. You can also [use AI to create and refine Campaigns](#create-and-refine-campaigns-using-ai), generating a structured overview and drafting messages through a conversational chat interface. > **Note:** Though named similarly, [Campaign Categories](https://www.airship.com/docs/reference/glossary/#campaign_categories) are a separate feature and have no connection to Campaigns. ## Create a Campaign To create a Campaign using an AI chat interface, see [Create and refine Campaigns using AI](#create-and-refine-campaigns-using-ai). To create a Campaign manually: 1. Select the **Create** dropdown menu (▼), then **Campaign**. Or go to **Campaigns**, and then select **Add Campaign**. 1. Select the default Campaign name and change it to something descriptive, and then select the submit icon (✓) to save it. Now you can add [existing messages](#add-existing-messages) or [new messages](#add-new-messages). You can also [add messages from a composer](#add-messages-from-a-composer). ### Add existing messages After opening a Campaign, select **Add ▼**, then select **Add existing**. You can search for messages by name and use the following filters: * **Status** — Select from Active, Draft, Paused, or Scheduled status. * **Message Type** — Select a composer: * Message — *Includes variants created in an [A/B test](https://www.airship.com/docs/guides/experimentation/a-b-tests/messages/)* * Scene * Sequence * Automation * In-App Automation * A/B Test — *[Legacy](https://www.airship.com/docs/guides/experimentation/a-b-tests/messages-legacy/)* Select at least one message by checking the box in its row, and then select **Add to Campaign**. You will return to the Campaign messages list. ### Add new messages After opening a Campaign, select **Add ▼**, and then select a composer: * Message * Automation * In-App Automation * Scene * A/B Test — *[Legacy](https://www.airship.com/docs/guides/experimentation/a-b-tests/messages-legacy/)* You can also select **Journey** to configure a Sequence, In-App Automation, or Scene in the [Journey Map](https://www.airship.com/docs/reference/glossary/#journey_map). For **Journey**, you can complete configuration in the map. For all other options, after completing configuration, you will return to the Campaign messages list. ### Add messages from a composer To add a message to a Campaign while composing: 1. Select **Campaign** above the message name. If the message is already assigned to a Campaign, the Campaign name will appear there instead. 1. Search for and select a Campaign, or select **Create** to create a new one. ![In composers, the Campaign name appears above the message name](https://www.airship.com/docs/images/campaign-name_hu_dc0f4f66853164d3.webp) *In composers, the Campaign name appears above the message name* ## Create and refine Campaigns using AI [AXP](https://www.airship.com/docs/reference/feature-packages/) [Agentic & Generative AI](https://www.airship.com/docs/guides/features/intelligence-ai/ai/) Use the Campaigns AI Agent to create or refine a Campaign through a conversational chat interface. Generate the [Campaign overview](#managing-campaigns) and draft or update messages from a prompt or by uploading a file. You can chat with the agent at any time to make additional updates to your Campaigns. The agent supports the following capabilities: * **Conversational editing and refinement** — Use natural language to iterate on your Campaign. Request changes like "Update the audience to loyalty members" or "Add a push notification for the launch date." * **Campaign planning** — Provide an objective, target audience, goals, and dates, and the agent will create a [structured overview](#managing-campaigns) that serves as the foundation for message creation. * **Message creation** — The agent uses the information in the overview as the foundation for drafting messages, ensuring content aligns with your goals and audience. It can create individual [messages](https://www.airship.com/docs/guides/messaging/messages/create/), [Scenes](https://www.airship.com/docs/reference/glossary/#scene), and [Sequences](https://www.airship.com/docs/reference/glossary/#sequence). However, it cannot create Open Channel messages or link components to create a [Journey](https://www.airship.com/docs/reference/glossary/#journey). Using the agent provides significant advantages: * **Faster planning** — Turn a brief or idea into a complete campaign strategy and drafted messages with less manual setup. * **Documented strategy** — Your strategy is captured in the overview before message creation begins, giving your team a shared reference as the campaign grows. * **Complete campaigns from incomplete briefs** — The agent identifies gaps in your prompt or file and asks targeted follow-up questions, so you can build a complete campaign even when you don't have all the details upfront. * **Consistent messaging** — Because all drafted messages are grounded in the same overview, the agent produces content that's consistent in tone, audience, and goals across the campaign. You can use the agent from the Campaigns list or after opening a Campaign: 1. Select **✨ Campaigns AI Agent**. 1. Enter a prompt describing your Campaign and/or upload a file. * Supported file formats: TXT and PDF. * The styles and personalities in your [brand guidelines](https://www.airship.com/docs/guides/messaging/features/brand-guidelines/) will be applied to the message design and content. * Explicit content is excluded. 1. Select the submit icon (↑) after each prompt or upload. After each generation completes, you can repeat these steps to continue editing. The agent will request additional information if needed to complete the overview. Once the minimum requirements have been met, it will prompt you to specify the messages you'd like to add and ask any questions needed to draft them. You can skip any item by saying "skip for now" or "I don't have that information yet" when asked. When you are finished using the agent, select the close icon (×). Your chat history persists in the current editing session, so you can close and reopen the agent without losing your chat. Select the remove icon (trash) to clear your chat history at any time. All messages are added as drafts. You must still review message content, configure any per-message audience targeting, and schedule or send manually. For Scenes, you can also use the [Native Experience AI Agent](https://www.airship.com/docs/guides/messaging/editors/native/ai-content/) for more fine-grained editing. > **Note:** **Opting In to AI Functions** > > If you opted out of AI usage, you must sign an updated contract to enable this feature. Contact your account manager for assistance. > > **Compliance Considerations in Using AI Functions** > > The Service incorporates AI functions, including Generative AI and Agentic AI. > > Generative AI generates content such as Notification copy, images, and Journeys based on your prompts. > > Agentic AI autonomously optimizes, personalizes, or executes cross-channel customer engagement actions, or analyzes audience and performance data, subject to the parameters and controls you set in the Service. These systems operate under human-defined parameters and do not initiate customer-facing actions without human interaction or pre-configured parameters. You are responsible for reviewing Generated Outputs for accuracy, appropriateness, and to ensure they do not violate third-party intellectual property or other rights. Airship does not publish Generated Outputs to end users without approval from the Customer. > > In addition to the applicable terms of your agreement with Airship (e.g., Use of Service, Customer Responsibilities sections), you must comply with the [Airship Acceptable Use Policy](https://www.airship.com/legal/acceptable-use/), which provides additional details about appropriate conduct when using the Service. > > The Service includes safety features to block harmful content, such as content that violates our Acceptable Use Policy. You may not attempt to bypass these protective measures or use content that violates your agreement with Airship. > > About the AI models: > > Airship utilizes Google Gemini and Imagen to generate copy and images for AI Scene screens. The content is created solely with Google's out-of-the-box models, and no customization or fine-tuning with Customer Data is applied. See [Responsible AI](https://cloud.google.com/responsible-ai?hl=en) in Google's *Google Cloud* documentation. ## Managing Campaigns Go to **Campaigns** to view all Campaigns in your project. Each Campaign is listed by name and date last modified, with the most recently modified Campaign listed first. You can search for Campaigns by name. To view or edit a Campaign, select its name from the list. To delete a Campaign, select the more menu icon (⋯), then select **Delete**. Once you open a Campaign, you can work in three views: * **Overview** — The Campaign objective, goals, audience, dates, and channel strategies are automatically populated when you [create and refine Campaigns using AI](#create-and-refine-campaigns-using-ai). **Channel Strategies** outlines each channel's name, specifies its role as either Primary for the main message or Secondary for supporting communication, and details the particular strategy employed for that channel within the campaign. * **Messages** — Each message is listed by name with its status, channels, and last modified date. Select the name or date column headers to sort. You can manage messages using these options: | Option | Description | Steps | | --- | --- | --- | | **Add message** | Add an existing message to the Campaign or create a new one. | See the steps for adding messages in [Create a Campaign](#create-a-campaign). | | **Edit message or open report** | Open the message in its origin composer or open its [message report](https://www.airship.com/docs/guides/reports/message/), [Scene report](https://www.airship.com/docs/guides/messaging/in-app-experiences/scenes/create/scene-reports/), or Sequence [Performance report](https://www.airship.com/docs/reference/glossary/#sequence_performance). Action availability depends on the status, and neither action is available for scheduled messages. | Select the message name. | | **Move message** | Move a message to a different Campaign. This action can be performed in bulk. | Select the check box for one or more messages, then select **Actions**, and then **Move to Campaign**. Then, search for and select a Campaign, or select **Create** to create a new one. | | **Remove message** | Remove a message from the Campaign. This action can be performed in bulk. | Select the check box for one or more messages, then select **Actions**, and then **Remove from Campaign** and confirm. | * **Calendar** — This functions the same as the [project-level calendar](https://www.airship.com/docs/guides/getting-started/ui/manage-views/#calendar) but includes only the messages in the Campaign. The Status and Message Type filters in the list and calendar views are the same as in the project-level calendar. However, the messages list includes an additional legacy A/B test filter option, as these messages are only displayed in the list view, not in the calendar. See the filter descriptions in [Visual indicators](https://www.airship.com/docs/guides/getting-started/ui/manage-views/#visual-indicators) in *Messages Overview and Calendar*. # Preference Centers > {{< glossary_definition "preference_center" >}} > **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. ## Overview ![Email Preference Center web page](https://www.airship.com/docs/images/email-preference-center_hu_9bd5a86c93881253.webp) *Email Preference Center web page* Preference Centers contain one or more page sections, each with an optional title and description. Add the text and sections you want in the page and select at least one [Subscription List](https://www.airship.com/docs/reference/glossary/#subscription_list) per section. You can also customize Subscription List names and descriptions to override those from your project settings. You can change a Preference Center in the Airship dashboard at any time. Your saved edits are published in real time. --- **Email** Preference Centers are Airship-hosted web pages. After creating the Preference Center in the dashboard, design a web page using our [Interactive editor](https://www.airship.com/docs/guides/messaging/editors/interactive/about/) and select a Preference Center to appear on the page. You can customize loading and saving status text and button labels and provide an Unsubscribe landing page URL. **No development work is required.** Then, include the web page link in emails you send to a Subscription List. You can also test the page's appearance in your web browser before making it available to your users. ![Web and App single-channel Preference Centers](https://www.airship.com/docs/images/app-web-preference-center_hu_988e0f107dd78166.webp) *Web and App single-channel Preference Centers* --- **App** and **Web** Preference Centers can be displayed as individual pages in your app or website or embedded in a page. After creating the Preference Center in the dashboard, give your developer the Preference Center ID so they can add it to your website or app. You can direct users to an App or Web Preference Center in multiple ways: * App and website navigation * Link or deep link * The Preference Center [Action](https://www.airship.com/docs/reference/glossary/#action) in a push notifications or in-app message * The Preference Center [Interactive button action](https://www.airship.com/docs/guides/messaging/editors/interactive/actions/) in a [Rich Page](https://www.airship.com/docs/reference/glossary/#rich_page) or [In-App Automation](https://www.airship.com/docs/reference/glossary/#iaa) ### Single- or multi-channel Preference centers can support either a single channel or multiple channels. Multi-channel Preference Centers can be configured for a single channel. Channel support, opt-in/out handling, and Airship plan requirements for each Preference Center type: | Type | Channel support | Opt-in/out handling1 | Plan requirement | | --- | --- | --- | --- | | **Single-channel** | App, web, email | Preferences are updated per channel. | Non-AXP | | **Multi-channel** | App, web, email, SMS | Preferences are updated at the [Named User](https://www.airship.com/docs/reference/glossary/#named_user) level per channel type. For example, if a user has two app channels and they update a preference for an app Subscription List, Airship updates both app channels for their named user, not just the one for the device they are on. | [AXP](https://www.airship.com/docs/reference/feature-packages/) | 1. See additional information in Subscription List opt-in/out handling per channel. In both Preference Center types, you can manually group Subscription Lists under headings you create. For multi-channel only, you also have the option to organize Subscription Lists automatically by channel: ![Layout options for a multi-channel (App and Email) Preference Center](https://www.airship.com/docs/images/preference-centers-multi-layout_hu_b49e61fe70045d65.webp) *Layout options for a multi-channel (App and Email) Preference Center* ### Subscription List opt-in/out handling per channel Subscription List opt-in status change handling for Preference Centers: | App and Web | Email | | --- | --- | | When a user changes their opt-in status for a Subscription List in a single-channel app or web Preference Center, their status is updated for the respective device or browser. For multi-channel, preferences are updated at the [Named User](https://www.airship.com/docs/reference/glossary/#named_user) level per channel type. | When a user follows the link from your email, the URL automatically inserts their [Channel ID](https://www.airship.com/docs/reference/glossary/#channel_id) and loads the web page, showing their email opt-in status for each email Subscription List in your project.

For a single-channel Preference Center, when a user changes their opt-in status and submits the form, the status is updated in Airship for the email address the message was sent to. For multi-channel, preferences are updated at the [Named User](https://www.airship.com/docs/reference/glossary/#named_user) level per channel type. | > **Important:** Changes users make in Preference Centers apply to the opt-in statuses for Subscription Lists only. **They do not control the opt-in status for receiving messages.** For example, if a user opts in to an SMS Subscription List in a Preference Center, they will not receive messages sent to that list unless they are already opted in to SMS notifications. See opt-in information per channel: > > * App > * [Android](https://www.airship.com/docs/developer/sdk-integration/android/push-notifications/getting-started/#enable-user-notifications) > * [iOS](https://www.airship.com/docs/developer/sdk-integration/apple/push-notifications/getting-started/#enable-user-notifications) > * [Web](https://www.airship.com/docs/developer/sdk-integration/web/push-notifications/) > * [Email](https://www.airship.com/docs/developer/api-integrations/email/getting-started/#register-users) > * [SMS](https://www.airship.com/docs/developer/api-integrations/sms/opt-in-out-handling/) ### Notification opt-in prompts and contact information ![An App opt-in prompt in an App Preference Center](https://www.airship.com/docs/images/opt-in-prompt_hu_f245118fcd30d8de.webp) *An App opt-in prompt in an App Preference Center* In an App Preference Center, you can add notification opt-in prompts for App, Web, Email, and SMS. They appear as embedded banners. For Email and SMS, users must add at least one email address or phone number, and users can manage addresses and numbers already opted in. All labels and fields within the prompts and modals are fully customizable. --- For **App and Web**, the prompt banner appears in the Preference Center on devices that have notifications disabled. You configure a single prompt for both App and Web that contains a button for opting in. Selecting the button opens the native notification settings for your app or a browser message asking the user to allow web notifications. For a web Preference Center, your web developer must code an action for the button. --- ![Opting in to SMS in an App Preference Center](https://www.airship.com/docs/images/pf-sms-opt-in_hu_353b6085d81efdde.webp) *Opting in to SMS in an App Preference Center* For **Email and/or SMS**, the prompt banner appears whether or not a user has added an email address or phone number. Opted-in addresses and phone numbers associated with a [Named User](https://www.airship.com/docs/reference/glossary/#named_user) are listed within the prompt banner. Users can add email addresses or phone numbers in order to opt in, add other addresses or numbers, or remove their contact information in order to opt out. Addresses or numbers added by the user are automatically associated with their Named User ID, allowing for cross-channel messaging. Users must complete the [Double Opt-In](https://www.airship.com/docs/reference/glossary/#double_opt_in) process in order to start receiving messages. Learn more about how double opt-in works for [Email](https://www.airship.com/docs/developer/api-integrations/email/getting-started/#double-opt-in) and [SMS](https://www.airship.com/docs/developer/api-integrations/sms/opt-in-out-handling/#double-opt-in). Your double opt-in workflow must be in place before saving an Email or SMS opt-in prompt in a Preference Center. When removing an email address, users are opted out of [Commercial Email](https://www.airship.com/docs/reference/glossary/#commercial_email) only. Required for Email and SMS opt-in prompts: [iOS SDK 18.6+](/docs/docs/developer/sdk-integration/apple/ios-changelog/#18.6.0) [Android SDK 18.1.2+](/docs/docs/developer/sdk-integration/android/changelog/#18.1.2) ### Reporting Changes to subscription status are recorded as [Real-Time Data Streaming](https://www.airship.com/docs/reference/glossary/#rtds) events. For single-channel Preference Centers, the events are per channel. For multi-channel, they include the [Named User](https://www.airship.com/docs/reference/glossary/#named_user). See [Subscription Event](https://www.airship.com/docs/developer/rest-api/connect/schemas/events/#subscription) and [Subscription List Event](https://www.airship.com/docs/developer/rest-api/connect/schemas/events/#subscription-list) in the *Real-Time Data Streaming API* reference. Even if you do not use Airship for all your channels, you can still use multi-channel Preference Centers for your other channels and keep your external providers in sync via Named User subscription status. ## Setup First, create the Preference Center in the dashboard, and then see the Implementation sections for App and Web or Email. > **Tip:** You can save an empty/undesigned Preference Center as a placeholder if your developer needs the ID immediately. ### Creating a Preference Center The [Company account Owner](https://www.airship.com/docs/guides/getting-started/admin/company-plan/) or a team member with [Administrator permission](https://www.airship.com/docs/guides/getting-started/admin/teams-messaging/#access-levels) can create and manage Preference Centers. You can create a maximum of 50 Preference Centers per project. 1. Next to your project name, select the dropdown menu (▼), then **Settings**. 1. Under **Project settings**, select **Preference Centers**. 1. Select **Create Preference Center**. 1. Define the Preference Center: | Field | Description | | --- | --- | | **Name and Description** | These appear in the Airship dashboard only. The Preference Center ID is automatically generated based on the name. An ID will not generate for a name that contains only numbers and/or special characters. | | **Type** | For single-channel Preference Centers only. Options: Mobile App, Web, Email. | | **ID** | You can enter your own ID instead of using the auto-generated one, using letters, numbers, and underscores. The ID must start with a letter and end with a letter or number. **You cannot change the ID later.** | {class="table-col-1-30"} 1. Select **Save and continue**. 1. (Multi-channel only) Select a layout. You can group Subscription Lists automatically by channel or manually under headings you create. If grouping by channel, select a channel to set up first. If a multi-channel Preference Center is organized by channel, Email automatically appears first. --- Now you can design the appearance of the Preference Center. 1. Set the title and description. For multi-channel Preference Centers, they apply to all selected channels. The Title is intended to appear as a page heading, with the Description appearing below. Their values apply to all channels, but appearance and control options vary: * For **apps**, they appear in the navigation bar at the top of your Preference Center. If you do not enter a title, the default title "Notifications" appears. * For **web**, your developer can control how they appear (or do not appear) in the Preference Center on your website. * For **email**, the title is a level-one HTML heading (`

`), and the description is an HTML paragraph (`

`). They inherit whatever styles apply more generally from the surrounding page. 1. (Optional for App Preference Centers) Add [notification opt-in prompts and contact information](#notification-opt-in-prompts-and-contact-information). Follow the steps in the [next section](#configuring-opt-in-prompts-and-contact-information). --- Next, configure page sections. Select **+ Add another section** for more page sections. Fields in each section: | Field | Description | Steps | | --- | --- | --- | | **Header** and **Description** | Optional. Text that appears above the Subscription Lists you add to the section. You may want to group related lists under a single header for better organization of your Preference Center.

For Web, your developer can control how these appear (or do not appear) in the Preference Center on your website. For Email, the header is a level-two HTML heading (`

`), and the description is an HTML paragraph (`

`). | Enter text. | | **Subscription Lists** | Determines which Subscription Lists will appear in the section. You can customize the list name and description for the current Preference Center. For multiple lists, you can set their order. | Search for and select at least one list. Select the more menu icon (⋮) for options to edit a list name and description, move it up in the order of lists, or remove it from the section. | {class="table-col-1-20 table-col-2-40"} For multi-channel Preference Centers grouped by channel: * To add channels, select **+ Add**, and select a channel. To remove a channel, select its tab, and then select **Remove channel**. Make sure to configure the page sections for each channel. * To customize channel names, select **Settings ▼**, then **Channel names**, enter the names as you want them to appear in the Preference Center, then select **Save**. If you want to change the name and description of a Subscription List, you must edit the list itself. See [Managing Subscription Lists](https://www.airship.com/docs/guides/audience/segmentation/audience-lists/subscription/#managing-subscription-lists). --- When you have completed configuration, select **Save and publish**. ### Configuring opt-in prompts and contact information When [creating an App Preference Center](#creating-a-preference-center), you can add a section that [prompts the user to opt-in to messaging and where they can manage their email addresses and phone numbers](#notification-opt-in-prompts-and-contact-information). > **Important:** Make sure your [Double Opt-In](https://www.airship.com/docs/reference/glossary/#double_opt_in) workflow is in place before saving an Email or SMS opt-in prompt in a Preference Center. 1. Under **Opt-in prompts**, select **Add +** next to **App/Web**, **Email**, or **SMS**. 1. (For App/Web) Configure fields for the title, body, button label, and button accessibility description. The accessibility description is optional text to be announced by assistive technology, such as screen readers. This overrides the announcement of the button label text. Selecting the button opens the native notification settings for your app or a browser message asking the user to allow web notifications. 1. (Optional for App/Web) Add an icon image. No icon is present by default. Enter an HTTPS URL for an icon image. The icon image may not render in preview. Open your app to review its appearance. See also [Personalizing media URLs](https://www.airship.com/docs/guides/personalization/content/personalize-actions/#media-urls).

If your Airship plan includes CDN support, you can also upload media or select from previous uploads in your project’s media library. See Insert media in message content in Media library.

1. (For Email and SMS)[iOS SDK 18.6+](/docs/docs/developer/sdk-integration/apple/ios-changelog/#18.6.0) [Android SDK 18.1.2+](/docs/docs/developer/sdk-integration/android/changelog/#18.1.2) Configure fields for each step: | Step | Format | Purpose and actions | Fields | | --- | --- | --- | --- | | **Prompt** | Embedded banner | The body should inform the users about the communications they are opting/opted into. Before entering an email address or phone number, customizable text appears next to an info icon (ⓘ). Afterward, the text is replaced with obfuscated contact information and a link for resending the verification email or text message also appears. Selecting the button opens the contact information form. | **Title**, **Body**, **Info** (If no contact information is present), **Button label: Add email address or phone number**, **Link label: Resend verification email or text message** | | **Contact information form** | Modal | This appears to the user after selecting a button for adding an email address or phone number. The body should inform the user that they will receive a verification email or text message they must respond to in order to complete opting in.

For SMS country code, you must select at least one [Sender ID](https://www.airship.com/docs/reference/glossary/#sender_id) to populate the country code menu that will appear in the Preference Center. You can select a single sender ID per country.

The Footer can be used for details and disclaimers, and you can add links using Markdown in the format `[Terms & Conditions](https:/www.example.com/terms)`. | **Title**, **Body**, **Email field** (Email only), **Email placeholder** (Email only), **Country code heading** (SMS only), **Country code menu** (SMS only), **Phone number field** (SMS only), **Button label: Cancel**, **Button label: Submit**, Footer | | **Confirmation: Contact information submitted** | Modal | This appears after the user submits the contact information form. The body should inform the user they successfully submitted their contact information and to check for the verification email or text message. Selecting the button closes the modal. | **Title**, **Body**, **Button label: Close** | | **Confirmation: Verification message resent** | Modal | This appears when the user selects the link for resending the verification email or text message. The body should inform the user that the verification message resent. Selecting the button closes the modal. | **Title**, **Body**, **Button label: Close** | | **Confirmation: Opt-out** | Modal | This appears when a user selects the remove icon (trash) to remove an email address or phone number. The body should inform the user they will be opted out of messaging for that address or number. For email, users are opted out of [Commercial Email](https://www.airship.com/docs/reference/glossary/#commercial_email) only. Selecting either button closes the modal. | **Title**, **Body**, **Button label: Cancel**, **Button label: Submit** | {class="table-col-1-20 table-col-2-20"} 1. Select **Save**. 1. Complete the remaining steps for [creating the Preference Center](#creating-a-preference-center). ### Implementation: App and Web Your app or web developer must place your Preference Center widget in the desired area of your app or website. If you included a [notification opt-in prompt](#configuring-opt-in-prompts-and-contact-information) for Web, your web developer must also code an action for the button. 1. Go to **Content**, then **Web Pages**. 1. Copy the ID for a Preference Center. 1. Give the ID and the following platform docs links to your developer. See: * Preference Center documentation for [SDK integrations](https://www.airship.com/docs/developer/sdk-integration/) * [Preference Center](https://www.airship.com/docs/developer/sdk-integration/web/advanced/preference-center/) for Web ### Implementation: Email Next, create the Airship-hosted web page where you will embed your Preference Center: 1. Go to **Content**, then **Web Pages**. 1. Select **Create web page**. 1. Enter a name and description for your Preference Center web page, and select **Continue**. These fields are for use within the Airship dashboard only and do not appear in your form. Description is optional. 1. Select **Add +** for HTML and select a default or [saved layout](https://www.airship.com/docs/guides/messaging/editors/interactive/saving-layouts/), or select **Blank Layout** to design your own. You can edit any layout after selecting. Then design the page. See [Interactive editor](https://www.airship.com/docs/guides/messaging/editors/interactive/about/) for details. * Your layout must include at least one Preference Center element. * Personalization is not supported. * A placeholder is shown within the Interactive editor, not your Preference Center design. * Select **Preview** to see how the web page will appear on desktop and mobile devices. 1. Select **Done** when you are finished designing the page. 1. Select **Save web page** to return to the list of all web pages in your project. #### Testing an Email Preference Center web page After [Creating an Email Preference Center web page](#creating-an-email-preference-center-web-page), you can see how it will appear to your users by sending its link in an email to a [Test Group](https://www.airship.com/docs/reference/glossary/#preview_test_groups) or by manually editing the web page URL. > **Note:** If you intend to send the message to your users immediately, use the [*Send Test* option in the *Review* step](https://www.airship.com/docs/guides/messaging/messages/create/#message-review) instead. To send a test email: 1. If you do not already have a Test Group, create or edit one now, adding yourself as a member using your email address. See [Preview and test groups](https://www.airship.com/docs/guides/audience/preview-test-groups/). 1. Go to **Content**, then **Web Pages**. 1. Select the more menu icon (⋯) for a web page, then **Copy link to clipboard**. 1. In the sidebar, select the **Create** dropdown menu (▼), then select **Message**, and complete the steps for the [Message composer](https://www.airship.com/docs/guides/messaging/messages/create/). * In the Audience step, enable the Email channel, then select Test Users, enter your test group name, and select from the results. * In the Content step, include the Preference Center link in the body of the email. * In the Delivery step, select **Send Now**. 1. After sending, check your email for your test message, and follow the Preference Center link. --- To test the web page without sending a message, add a [Channel ID](https://www.airship.com/docs/reference/glossary/#channel_id) to the Preference Center's URL: > **Warning:** Interacting with the web page will apply changes to the channel ID you use for testing. 1. Go to **Content**, then **Web Pages**. 1. Select the more menu icon (⋯) for a web page, then **Copy link to clipboard**. 1. Paste the URL in your browser's address bar, replace `{{$channel.id}}` with an actual channel ID, and hit Enter on your keyboard. You should now see your rendered Email Preference Center web page. ## Directing users to a Preference Center In addition to adding a Preference Center to your app or website or providing a link or deep link, you use can Airship's built-in actions to open a Preference Center when a user interacts with a message or taps a button: * For push notifications and in-app messages, select the Preference Center [Action](https://www.airship.com/docs/reference/glossary/#action) in the Content step in a Message, Automation, A/B Test, or Sequence. * For [Rich Pages](https://www.airship.com/docs/reference/glossary/#rich_page) and [In-App Automation](https://www.airship.com/docs/reference/glossary/#iaa), select the Preference Center button action when configuring content using the Interactive editor. See [Actions in the Interactive editor](https://www.airship.com/docs/guides/messaging/editors/interactive/actions/). --- For Email Preference Centers, add the URL as a link in an [email message](https://www.airship.com/docs/guides/messaging/messages/content/email/email/) or [Template](https://www.airship.com/docs/reference/glossary/#template). To get the web page URL: 1. Go to **Content**, then **Web Pages**. 1. Select the more menu icon (⋯) for a web page, then **Copy link to clipboard**. You must send your email using Airship. The Preference Center will not load for a user if sent from a system other than Airship. Only link to an email Preference Center from an email. ## Managing Preference Centers The [Company account Owner](https://www.airship.com/docs/guides/getting-started/admin/company-plan/) or a team member with [Administrator permission](https://www.airship.com/docs/guides/getting-started/admin/teams-messaging/#access-levels) can create and manage Preference Centers and web pages. Select the dropdown icon (▼) next to your project name, then **Settings**. Under **Project settings**, select **Preference Centers**. The most recently modified Preference Center appears first. Select a column header to sort by name, ID, date created, or date modified. Select the **Archived** filter to see all archived Preference Centers. | Option | Description | Steps | | --- | --- | --- | | **Edit name and description (Single-channel)** | The name and description appear in the dashboard only. | Select the edit icon ( ), then the ( ) next to the name. Update the name or description, then select **Continue**, then **Save and publish**. | | **Edit name and description (Multi-channel)** | The name and description appear in the dashboard only. | Select the edit icon ( ), then **Settings ▼**, and then **Preference Center details**. Edit the name or description, then select **Save**, then **Save and publish**. | | **Change layout (Multi-channel only)** | You can switch between grouping by category or channel. | Select the edit icon ( ), then **Settings ▼**, then **Preference center details**, then **Select a different layout**. Make a selection, and the Preference Center will reload with the new layout. | | **Customize channel names (Multi-channel only)** | You set the channel names as they appear in the Preference Center. Channel names only appear when the Preference Center is grouped by channel and when more than one channel is added to the Preference Center. | Select the edit icon ( ), then **Settings ▼**, and then **Channel names**. Update the channel names, then select **Save**, then **Save and publish**. | | **Edit content** | You can edit the Preference Center at any time. Changes are published immediately. | Select the edit icon ( ), update the design, then select **Save and publish**. | | **Duplicate** | Makes a copy of the Preference Center with " copy" appended to the original name. | Select the duplicate icon ( ), edit the name, ID, and description, and select a type (required for single-channel Preference Centers only). Then select **Save and continue** and follow the steps in [Creating a Preference Center](#creating-a-preference-center). | | **Archive** | Available when **Published** filter is enabled. Removes the Preference Center from your list of published Preference Centers. This action does not affect its use in an app, website, or Airship-hosted web page. Archived Preference Centers count toward the maximum of 50. **Deleting a web page invalidates its URL.** | Select the archive icon ( ). For multi-channel Preference Centers, you can also archive by going selecting the edit icon ( ), then **Settings ▼**, then **Preference Center details**, then **Archive Preference Center**. | | **Unarchive** | Available when **Archived** filter is enabled. Restores the Preference Center to your list of published Preference Centers. | Select the archive icon ( ). | > **Note:** As of May 24, 2022, [AXP customers](https://www.airship.com/docs/reference/feature-packages/) can create multi-channel Preference Centers only. Previously created single-channel Preference Centers: > * Cannot be duplicated > * Can be edited — *Name and description only* > * Can be archived > > See [Migrating to a user-level Preference Center](#migrating-to-a-user-level-preference-center). ## Managing web pages Go to **Content** and select **Web Pages** to view the list of email Preference Center web pages in your project. Your last modified web page is listed first. You can sort the list by name or date modified, and search by name or keyword. Select a web page name to open a drawer where you can do the following: * For the web page link, select the copy icon (clipboard) to copy it to your clipboard. * Edit the name, description, and keywords. Select **Save** after making your changes. * Select **Edit** or **Duplicate**, which are the same as the actions available from the more menu icon (⋯), as described in the table below. * View the date and time when the web page was created and last modified. The following actions are available from the more menu icon (⋯) in the web pages list: | Action | Description | Steps | | --- | --- | --- | | **Edit** | Open the web page for editing. You can change the content, name, and description. | Select the more menu icon (⋯), then **Edit**, make your changes, and then select **Save web page**. | | **Duplicate** | Make a copy of the web page in the current project or in a different project.

Airship does not copy Segments, Attributes, Custom Events, Deep Links, Subscription Lists, Preference Centers, brand guidelines, or Scene settings. Configure those resources independently in each project. | First, choose to copy to the current project or a different one, and update the name, description, and keywords. Then, select **Duplicate**. | | **View information and access additional actions** | Open the same drawer as when you select a web page name. For what you can do in the drawer, see the list above this table. | Select the more menu icon (⋯), then **View detail**. | | **Delete** | Delete the web page from your project.

**Deleting a web page invalidates its URL.** Consider editing the web page if you want to keep the link active in emails you have already sent. | Select the more menu icon (⋯), then **Delete**. | | **Copy link to clipboard** | Copy the web page link to your clipboard. | Select the more menu icon (⋯), then **Copy link to clipboard**. | {class="table-col-1-20 table-col-2-40"} ## Migrating to a user-level Preference Center Single-channel Preference Centers created before October 10, 2022, update at the channel level. After migrating to a user-level Preference Center, preferences are updated at the [Named User](https://www.airship.com/docs/reference/glossary/#named_user) level per channel type. For instance, if a user has two app channels and they update a preference for an app Subscription List, then Airship updates both app channels for their named user, not just the one for the device they are on. **Do not migrate until your SDK has been updated.** * [Android migration guides](https://github.com/urbanairship/android-library/tree/main/documentation/migration) * [iOS migration guides](https://github.com/urbanairship/ios-library/tree/main/Documentation/Migration) > **Warning:** Migration is permanent. You cannot migrate a user-level Preference Center to channel-level. 1. Next to your project name, select the dropdown menu (▼), then **Settings**. 1. Under **Project settings**, select **Preference Centers**. 1. Select the edit icon ( ) for a Preference Center. 1. Select **Start migration process**. This option only appears if the Preference Center is currently channel-level. 1. Check the terms box and select **Migrate Preference Center**. Migration takes seconds to complete. 1. Select **Save and publish** to apply the changes. # Android Live Updates > Add and manage Android Live Updates using the push API. {{< badge "axp" >}} For SDK methods, see the [Live Updates](https://www.airship.com/docs/sdk-topics/live-updates/) developer documentation. See also the [Android Live Updates](https://www.airship.com/docs/guides/features/messaging/live-activities-updates/) feature guide. ## About implementation Live Updates can be started, updated, and ended using API push notifications or the SDK. The notification, widget, or custom app view refreshes with the information contained in the latest Live Update received by the device. First you must implement a handler and define its type. This determines what occurs in the app when it receives a Live Update. Then register the handler with the Airship SDK so the handler can be notified upon receiving a `live_update` payload. Then start the Live Update by sending a push or implementing custom code. When you start the Live Update, you define its name in the `live_update` object. You can update and end by sending additional pushes or using the `LiveUpdateManager`. * Types must be unique for each `LiveUpdateHandler` defined by an app. * A handler can handle multiple uniquely named Live Updates. * A name can be unique for a [Channel ID](https://www.airship.com/docs/reference/glossary/#channel_id) (e.g., `order-12345`) or shared across multiple channel IDs (e.g., `sports-game-123`). * A name can be reused after its Live Update has ended. For example, to provide updates for tracking a sports game, start a Live Update with name `sports-game-123`. The app will track and display changes through the Airship SDK using that name. ## Creating a handler The Airship SDK supports two types of Live Update handlers: * `NotificationLiveUpdateHandler` — Displays a notification with a custom layout, with content updated by the Live Update. * `CustomLiveUpdateHandler` — Receives Live Update events and provides flexibility to display content using a custom implementation. This can be used to power home screen widgets, views embedded in the app, and more. Each handler type has two different interfaces that may be implemented, to support suspending or callback-based code: * `SuspendLiveUpdateNotificationHandler` * `CallbackLiveUpdateNotificationHandler` * `SuspendLiveUpdateCustomHandler` * `CallbackLiveUpdateCustomHandler` The following `SampleLiveUpdateHandler` reads content from the Live Update payload and displays scores for a sports game in a custom notification layout, using `RemoteViews`: ```kotlin class SampleLiveUpdateHandler : SuspendLiveUpdateNotificationHandler() { override suspend fun onUpdate( context: Context, event: LiveUpdateEvent, update: LiveUpdate ): LiveUpdateResult { // Read content_state fields from the Live Update payload val teamOneScore = update.content.opt("team_one_score").getInt(0).toString() val teamTwoScore = update.content.opt("team_two_score").getInt(0).toString() val statusUpdate = update.content.opt("status_update").optString() // Expanded notification layout val bigLayout = RemoteViews(context.packageName, R.layout.sports_big).apply { setTextViewText(R.id.teamOneScore, teamOneScore) setTextViewText(R.id.teamTwoScore, teamTwoScore) setTextViewText(R.id.statusUpdate, statusUpdate) } // Collapsed notification layout val smallLayout = RemoteViews(context.packageName, R.layout.sports_small).apply { setTextViewText(R.id.teamOneScore, teamOneScore) setTextViewText(R.id.teamTwoScore, teamTwoScore) } // Create the notification builder val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) .setPriority(NotificationCompat.PRIORITY_HIGH) .setCategory(NotificationCompat.CATEGORY_EVENT) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) .setCustomContentView(smallLayout) .setCustomBigContentView(bigLayout) // Return 'ok' with the notification builder. // The Airship SDK will handle posting the notification. // Returning LiveUpdateResult.cancel() will end the Live Update and dismiss the notification. return LiveUpdateResult.ok(builder) } companion object { private const val NOTIFICATION_CHANNEL_ID = "sports" } } ``` ## Registering a handler Handlers must be registered with `LiveUpdateManager` in order to receive Live Update events. This should be done *once* after `takeOff`. #### Android Kotlin In your `Autopilot` class, or in `Application.onCreate`, register the types. ```kotlin class SampleAutopilot : Autopilot() { override fun onAirshipReady(airship: UAirship) { LiveUpdateManager.shared().run { register(type = "notification", handler = SampleLiveUpdateHandler()) } } } ``` #### React Native Using the [AirshipPluginExtender](https://www.airship.com/docs/developer/sdk-integration/react-native/installation/extending-airship/), register the types. ```kotlin @Keep public final class AirshipExtender: AirshipPluginExtender { override fun onAirshipReady(context: Context, airship: UAirship) { LiveUpdateManager.shared().run { register(type = "notification", handler = SampleLiveUpdateHandler()) } } } ``` #### Capacitor Using the [AirshipPluginExtender](https://www.airship.com/docs/developer/sdk-integration/capacitor/installation/extending-airship/), register the types. ```kotlin @Keep public final class AirshipExtender: AirshipPluginExtender { override fun onAirshipReady(context: Context, airship: UAirship) { LiveUpdateManager.shared().run { register(type = "notification", handler = SampleLiveUpdateHandler()) } } } ``` #### Flutter Using the [AirshipPluginExtender](https://www.airship.com/docs/developer/sdk-integration/flutter/installation/extending-airship/), register the types. ```kotlin @Keep public final class AirshipExtender: AirshipPluginExtender { override fun onAirshipReady(context: Context, airship: UAirship) { LiveUpdateManager.shared().run { register(type = "notification", handler = SampleLiveUpdateHandler()) } } } ``` > **Note:** The `type` used above, `"notification"`, is used to map Live Update events to the corresponding handler in your app. > The value can be any string that is unique across all handlers registered by an app. This also allows a single handler to manage multiple Live Updates that each have a unique `name`. ## Starting Live Updates Once a handler has been registered, Live Updates can be started via the [Push API](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) by specifying a [`live_update` payload](https://www.airship.com/docs/developer/rest-api/ua/schemas/platform-overrides/#androidoverrideobject). In this example, a Live Update will be started for all Android devices that have the tag `"sports-scores"`: ```json { "device_types": [ "android" ], "audience": { "tag": "sports-scores" }, "notification": { "android": { "live_update": { "name": "sports-game-123", "type": "notification", "event": "start", "content_state": { "team_one_score": 0, "team_two_score": 0, "status_update": "Game started!" } } } } } ``` Live Updates can also be started from within the app. #### Android Kotlin ```kotlin LiveUpdateManager.shared().start( name = "sports-game-123", type = "notification", content = jsonMapOf( "team_one_score" to 0, "team_two_score" to 0, "status_update" to "Game started!" ) ) ``` #### React Native ```typescript Airship.android.liveUpdateManager.start({ name: 'sports-game-123' type: 'notification', content: { team_one_score: 0, team_two_score: 0, status_update: 'Game started!' } }); ``` #### Capacitor ```typescript Airship.android.liveUpdateManager.start({ name: 'sports-game-123' type: 'notification', content: { team_one_score: 0, team_two_score: 0, status_update: 'Game started!' } }); ``` #### Flutter ```dart if (Platform.isAndroid) { LiveUpdateStartRequest createRequest = LiveUpdateStartRequest( name: "sports-game-123", type: 'notification', content: { 'team_one_score': 0, 'team_two_score': 0, 'status_update': 'Game started!' } ); await Airship.liveUpdateManager.start(createRequest); } ``` ## Updating Live Updates Now that the Live Update is started, the content can be updated via the [Push API](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) with the following payload. This example will send an update to all Android channels that have a Live Update named `sports-game-123`. The `audience` field can be specified to restrict who receives the update. ```json { "device_types": [ "android" ], "audience": "all", "notification": { "android": { "live_update": { "name": "sports-game-123", "event": "update", "content_state": { "team_one_score": 3, "team_two_score": 0 } } } } } ``` Live Updates can also be updated from within the app. #### Android Kotlin ```kotlin LiveUpdateManager.shared().update( name = "sports-game-123", content = jsonMapOf( "team_one_score" to 3, "team_two_score" to 0, "status_update" to "Game started!" ) ) ``` #### React Native ```typescript Airship.android.liveUpdateManager.update({ name: 'sports-game-123' content: { team_one_score: 3, team_two_score: 0, status_update: 'Game started!' } }); ``` #### Capacitor ```typescript Airship.android.liveUpdateManager.update({ name: 'sports-game-123' content: { team_one_score: 3, team_two_score: 0, status_update: 'Game started!' } }); ``` #### Flutter ```dart if (Platform.isAndroid) { List updates = await Airship.liveUpdateManager.listAll(); LiveUpdateUpdateRequest request = LiveUpdateUpdateRequest( name: "sports-game-123", content: { 'team_one_score': 0, 'team_two_score': 0, 'status_update': 'Game started!' } ); await Airship.liveUpdateManager.update(request); } ``` ## Ending Live Updates To end a Live Update via the [Push API](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush), send the following payload: ```json { "device_types": [ "android" ], "audience": "all", "notification": { "android": { "live_update": { "name": "sports-game-123", "event": "end", "content_state": { "team_one_score": 9, "team_two_score": 6, "status_update": "Game over!" } } } } } ``` #### Android Kotlin ```kotlin LiveUpdateManager.shared().stop( name = "sports-game-123", content = jsonMapOf( "team_one_score" to 9, "team_two_score" to 6, "status_update" to "Game over!" ) ) ``` #### React Native ```typescript Airship.android.liveUpdateManager.end({ name: 'sports-game-123' content: { team_one_score: 9, team_two_score: 6, status_update: 'Game over!' } }); ``` #### Capacitor ```typescript Airship.android.liveUpdateManager.end({ name: 'sports-game-123' content: { team_one_score: 9, team_two_score: 6, status_update: 'Game over!' } }); ``` #### Flutter ```dart if (Platform.isAndroid) { List updates = await Airship.liveUpdateManager.listAll(); LiveUpdateEndRequest stopRequest = LiveUpdateEndRequest( name: "sports-game-123" ); await Airship.liveUpdateManager.end(stopRequest); } ``` ## Clearing all active Live Updates During development, it can be useful to reset Live Update tracking on app launch. This allows any Live Updates to be started fresh, even if they were already started during a previous launch. To end all currently active Live Updates, call the `clearAll()` method on `LiveUpdateManager`. #### Android Kotlin ```kotlin LiveUpdateManager.shared().clearAll() ``` #### React Native ```typescript Airship.android.liveUpdateManager.clearAll(); ``` #### Capacitor ```typescript Airship.android.liveUpdateManager.clearAll(); ``` #### Flutter ```dart if (Platform.isAndroid) { await Airship.liveUpdateManager.clearAll(); } ``` # iOS Live Activities > Add and manage iOS Live Activities using the push API. {{< badge "axp" >}} For SDK methods, see the [Live Activities](https://www.airship.com/docs/sdk-topics/live-activities/) developer documentation. See also the [iOS Live Activities](https://www.airship.com/docs/guides/features/messaging/live-activities-updates/) feature guide. ## About implementation Updates to Live Activities are made through push notifications and/or background tasks in the app. For more timely updates, Airship recommends using push notifications or push notifications in addition to background tasks. When updating through push notifications, APNs allows a certain budget of updates per hour. If an app exceeds this budget, notifications will be throttled. To avoid being throttled, a mix of low priority (priority 5) and high priority notifications (priority 10) can be used. In addition to priorities and background tasks, if a use case requires frequent push updates, an app can also set the plist flag [NSSupportsLiveActivitiesFrequentUpdates](https://developer.apple.com/documentation/bundleresources/information_property_list/nssupportsliveactivitiesfrequentupdates) to prevent being throttled. However, the end user is able to disable frequent updates in the app settings. For more information on implementing Live Activities, see Apple documentation: * [ActivityKit developer guide](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities) * [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines) ### Naming Live Activities Airship's Live Activity support allows starting Live Activities through a push and tracking each Live Activity's unique push token by a name on the app's channel. The name can then be used to send updates to a Live Activity. The name can be unique to the device or shared across multiple devices. Airship handles mapping the name back to the token for the specified audience and sends an update to each token. All tokens are tracked under the device channel. They do not increase your billable audience. In order to support starting a Live Activity from both a push notification and locally, it is recommended that you provide the name you will use to track the activity in the activity's attributes, and required if you are trying to support Live Activities from a framework. For example, to provide updates for tracking a sports game, create a Live Activity with name `sports-game-123`. Add the id of the game to the Activity's attributes as `gameID`: ```swift struct SportsActivityAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { // Mutable content val status: String } // GameID var gameID: String } ``` > **Important:** Live Activities require token-based authentication for APNs. See [iOS Channel Configuration](https://www.airship.com/docs/guides/getting-started/developers/configure-channels/#ios-channel-configuration). ## App setup #### iOS Swift To support Live Activities, you must call restore *once* after takeOff during `application(_:didFinishLaunchingWithOptions:)` with all the Live Activity types that you might track with Airship. This allows Airship to resume tracking any previously tracked activities across app inits and to automatically track the `pushToStartToken` that allows starting activities through a push notification. ```swift Airship.takeOff(config, launchOptions: launchOptions) Airship.channel.restoreLiveActivityTracking { restorer in await restorer.restore(forType: Activity.self) await restorer.restore(forType: Activity.self) } ``` After the `restore` call above, Airship will track the `pushToStartTokens` for the activity's attribute types. You can then start a Live Activity through a push notification. Starting a Live Activity does not automatically track it. Instead, the app will be woken up and you must call through to Airship with the activity instance and the name. There is no entry point into the app when it is started for a Live Activity being created. Instead, you need to query Live Activities on init and when a `pushToStartToken` update is received to track them through Airship. Airship provides an extension `Activity.airshipWatchActivities(activityBlock:)` that can be used to do this for you. In this example, we assume the `gameID` on our `SportsActivityAttributes` will be used to send updates through Airship after it is created: ```swift Airship.channel.restoreLiveActivityTracking { restorer in await restorer.restore(forType: Activity.self) } Activity.airshipWatchActivities { activity in Airship.channel.trackLiveActivity(activity, name: activity.attributes.gameID) } ``` #### React Native Using the [AirshipPluginExtender](https://www.airship.com/docs/developer/sdk-integration/react-native/installation/extending-airship/), make a call to `LiveActivityManager.shared.setup` to configure any Live Activities for the app. Call `configurator.register` for each Live Activity type that your application defines and include a block on how to parse the name of the activity that you will use to track on Airship. This name will be used to send updates through APNS. ```swift import Foundation import AirshipKit import AirshipFrameworkProxy import ActivityKit // This class header is required to be automatically picked up by the Airship plugin: @objc(AirshipPluginExtender) public class AirshipPluginExtender: NSObject, AirshipPluginExtenderProtocol { public static func onAirshipReady() { if #available(iOS 16.1, *) { // Will throw if called more than once try? LiveActivityManager.shared.setup { configurator in // Call for each Live Activity type await configurator.register(forType: Activity.self) { attributes in // Track this property as the Airship name for updates attributes.gameID } } } // other setup } } ``` > **Important:** If you are using Expo, you must copy-paste your exact `ActivityAttributes` struct into your `AirshipPluginExtender.swift` so the compiler can find a definition in order to register the Live Activity. #### Capacitor Using the [AirshipPluginExtender](https://www.airship.com/docs/developer/sdk-integration/capacitor/installation/extending-airship/), make a call to `LiveActivityManager.shared.setup` to configure any Live Activities for the app. Call `configurator.register` for each Live Activity type that your application defines and include a block on how to parse the name of the activity that you will use to track on Airship. This name will be used to send updates through APNS. ```swift import Foundation import AirshipKit import AirshipFrameworkProxy import ActivityKit // This class header is required to be automatically picked up by the Airship plugin: @objc(AirshipPluginExtender) public class AirshipPluginExtender: NSObject, AirshipPluginExtenderProtocol { public static func onAirshipReady() { if #available(iOS 16.1, *) { // Will throw if called more than once try? LiveActivityManager.shared.setup { configurator in // Call for each Live Activity type await configurator.register(forType: Activity.self) { attributes in // Track this property as the Airship name for updates attributes.gameID } } } // other setup } } ``` #### Flutter Using the [AirshipPluginExtender](https://www.airship.com/docs/developer/sdk-integration/flutter/installation/extending-airship/), make a call to `LiveActivityManager.shared.setup` to configure any Live Activities for the app. Call `configurator.register` for each Live Activity type that your application defines and include a block on how to parse the name of the activity that you will use to track on Airship. This name will be used to send updates through APNS. ```swift import Foundation import AirshipKit import AirshipFrameworkProxy import ActivityKit // This class header is required to be automatically picked up by the Airship plugin: @objc(AirshipPluginExtender) public class AirshipPluginExtender: NSObject, AirshipPluginExtenderProtocol { public static func onAirshipReady() { if #available(iOS 16.1, *) { // Will throw if called more than once try? LiveActivityManager.shared.setup { configurator in // Call for each Live Activity type await configurator.register(forType: Activity.self) { attributes in // Track this property as the Airship name for updates attributes.gameID } } } // other setup } } ``` ## Starting Live Activities > **Note:** When you **start** a Live Activity from a push notification, you should limit which devices receive the push by specifying the `audience` on the push request unless you want your entire iOS audience to start the Live Activity. Live Activities can be started via the [Push API](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) by specifying a [`live_activity` payload](https://www.airship.com/docs/developer/rest-api/ua/schemas/platform-overrides/#iosoverrideobject) for the event `start`. In this example, a Live Activity will be started for all iOS devices that have the tag `"sports-scores"`: ```json { "audience": { "tag": "sports-score", }, "device_types": [ "ios" ], "notification": { "ios": { "live_activity": { "event": "start", "attributes_type": "SportsActivityAttributes", "attributes": { "gameID": "sports-game-123" }, "content_state": { "status": "Game about to begin!" }, "alert": { "title": "Game about to begin", "body": "Tune in!" }, "priority": 10 } } } } ``` Live Updates can also be started from within the app when: * Anytime the app is in the foreground * From activity intent * From a notification action button #### iOS Swift To start a Live Activity from the app, make sure to set the pushType to `.token`. After it is started, immediately track it with `Airship.channel.trackLiveActivity(_:name:)`. ```swift let activity = try Activity.request( attributes: attributes, content: content, pushType: .token ) Airship.channel.trackLiveActivity( activity, name: attributes.gameID ) ``` #### React Native For any Live Activities configured, you can start a new one using the `start` method: ```typescript Airship.iOS.liveActivityManager.start({ attributesType: 'SportsActivityAttributes', content: { state: { status: 'Game Pending', }, relevanceScore: 0.0, }, attributes: { gameID: 'sports-game-123', }, }); ``` #### Capacitor For any Live Activities configured, you can start a new one using the `start` method: ```typescript Airship.iOS.liveActivityManager.start({ attributesType: 'SportsActivityAttributes', content: { state: { status: 'Game Pending', }, relevanceScore: 0.0, }, attributes: { gameID: 'sports-game-123', }, }); ``` #### Flutter For any Live Activities configured, you can start a new one using the `start` method: ```dart if (Platform.isIOS) { LiveActivityStartRequest startRequest = LiveActivityStartRequest( attributesType: 'SportsActivityAttributes', attributes: { "gameID": sports-game-123, }, content: LiveActivityContent(status: 'Game Pending', relevanceScore: 0.0)); await Airship.liveActivityManager.start(startRequest); } ``` ## Updating Live Activities Now that the Live Activity is started, the content can be updated via the [Push API](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) with the following payload. This example will send an update to all iOS channels that have a Live Update named `sports-game-123`. The `audience` field can be specified to restrict who receives the update. ```json { "audience": "all", "device_types": [ "ios" ], "notification": { "ios": { "live_activity": { "name": "sports-game-123", "event": "update", "content_state": { "status": "Game starting!" }, "alert": { "title": "Game is starting", "body": "Tune in!" }, "priority": 10, "stale_date": 1666261020, "relevance_score": 50 } } } } ``` Updates can also be made within the app. #### iOS Swift To update, user the standard ActivityKit APIs. First find the Activity instance then call `update` content on it: ```swift guard let activity = Activity.activities.first(where: { $0.id == "sports-game-123" }) else { // not found return } activity.update(contentUpdate) ``` #### React Native To update, use `update`, but you will need the activity ID. ```typescript const activities = await Airship.iOS.liveActivityManager.listAll(); const activity = activities.find( (activity) => activity.attributes.gameID === 'sports-game-123' ); if (activity) { Airship.iOS.liveActivityManager.update({ activityId: activity.id, content: { state: { status: "Game starting!" } relevanceScore: 0.0, }, }); } ``` #### Capacitor To update, use `update`, but you will need the activity ID. ```typescript const activities = await Airship.iOS.liveActivityManager.listAll(); const activity = activities.find( (activity) => activity.attributes.gameID === 'sports-game-123' ); if (activity) { Airship.iOS.liveActivityManager.update({ activityId: activity.id, content: { state: { status: "Game starting!" } relevanceScore: 0.0, }, }); } ``` #### Flutter To update, use `update`, but you will need the activity ID. ```dart if (Platform.isIOS) { List activities = await Airship.liveActivityManager.listAll(); LiveActivity? activity = activities .where((activity) => activity.attributes.gameID == 'sports-game-123') .firstOrNull; if (activity != null) { LiveActivityContent content = LiveActivityContent( state: {'status': 'Game starting!'}, relevanceScore: 0.0, ); LiveActivityUpdateRequest updateRequest = LiveActivityUpdateRequest( attributesType: 'SportsGameAttributes', activityId: activity.id, content: content, ); await Airship.liveActivityManager.update(updateRequest); } } ``` ## Ending Live Activities Live Activities will automatically expire after 8 hours and dismiss after 12. You can end and or dismiss a Live Activity earlier via the [Push API](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) with the following payload. This example will send end to all iOS channels that have a Live Update named `sports-game-123`. The `audience` field can be specified to restrict who receives the update. ```json { "audience": "all", "device_types": [ "ios" ], "notification": { "ios": { "live_activity": { "name": "sports-game-123", "event": "end", "priority": 10, "dismissal_date": 1666265020, "content_state": { "status": "Game ended" } } } } } ``` You can also end an activity within the app. #### iOS Swift To update, user the standard ActivityKit APIs. First find the Activity instance then call `update` content on it: ```swift guard let activity = Activity.activities.first(where: { $0.id == "sports-game-123" }) else { // not found return } activity.end(contentUpdate, dismissalPolicy: .default) ``` #### React Native To end is similar to `update`. Use `end` with the activity ID: ```typescript const activities = await Airship.iOS.liveActivityManager.listAll(); const activity = activities.find( (activity) => activity.attributes.gameID === 'sports-game-123' ); if (activity) { Airship.iOS.liveActivityManager.end({ activityId: activity.id, dismissalPolicy: { type: "default" } }); } ``` #### Capacitor To end is similar to `update`. Use `end` with the activity ID: ```typescript const activities = await Airship.iOS.liveActivityManager.listAll(); const activity = activities.find( (activity) => activity.attributes.gameID === 'sports-game-123' ); if (activity) { Airship.iOS.liveActivityManager.end({ activityId: activity.id, dismissalPolicy: { type: "default" } }); } ``` #### Flutter To end is similar to `update`. Use `end` with the activity ID: ```dart if (Platform.isIOS) { List activities = await Airship.liveActivityManager.listAll(); LiveActivity? activity = activities .where((activity) => activity.attributes.gameID == 'sports-game-123') .firstOrNull; if (activity != null) { LiveActivityStopRequest stopRequest = LiveActivityStopRequest( attributesType: 'SportsGameAttributes', activityId: activity.id, dismissalPolicy: LiveActivityDismissalPolicyDefault(), ); await Airship.liveActivityManager.end(stopRequest); } } ``` # Opt-in forms > An opt-in form is a form you can add to your website, where your users can sign up for email or SMS messaging. ## About opt-in forms Airship provides the methods to render an opt-in form via plugin in our Web SDK. You can choose either to embed the form in your site or display in a modal window. Both embedded and modal versions are available in large and small formats. The forms require the Airship [Web SDK](https://www.airship.com/docs/developer/sdk-integration/web/getting-started/), and will adopt the stylings from your site's CSS, but can be customized or adjusted further. **User registration handling:** * *Email* — When an email address is submitted through the form, the address is registered for transactional emails. By default, it is also registered for commercial emails, or you may specify an option to request [[Double Opt-In](https://www.airship.com/docs/reference/glossary/#double_opt_in)](https://www.airship.com/docs/developer/api-integrations/email/getting-started/#double-opt-in) for commercial messages. * *SMS* — When an [MSISDN](https://www.airship.com/docs/reference/glossary/#msisdn) is submitted through the form, Airship sends a message to that number, prompting them to opt in. For more information, see the SMS platform documentation: [Non-Mobile Double Opt-In](https://www.airship.com/docs/developer/api-integrations/sms/opt-in-out-handling/#non-mobile-double-opt-in). The SMS or Email channel will be associated with a named user if one has already been set at the time the channel is added. If the channel is created prior to a Named User being set, the information and all other data collected will be associated with an Anonymous [Contact](https://www.airship.com/docs/reference/glossary/#contact). The Anonymous Contact will be set by Airship, and when a new Named User is set, this data will be transferred to it. > **Note:** You must use individual forms for email and SMS; you cannot use the same for both channels. ## Adding a form to your website To add an opt-in form to your website, you must have the Airship [Web SDK](https://www.airship.com/docs/developer/sdk-integration/web/getting-started/) installed, and to render the form you must load the [Opt-in Forms plugin](https://www.airship.com/docs/developer/sdk-integration/web/plugins/opt-in-forms/). Once the SDK is installed and you are loading the plugin, you can choose to embed the form into an existing element on the page, or by displaying a modal to the user. > **Important:** The suggested opt-in text and the design and usage guidelines provided in the Documentation are not intended to be legal advice. The suggested text should not be used "as is", and is instead an example of what may meet opt-in standards or requirements. Please consult your legal counsel before implementing particular language for your campaigns to address your specific use case or regulatory requirements in your jurisdiction. Here's an example of an embedded email form, specifying only the required options, targeting the `email-opt-in` element. Place the HTML code anywhere on your website: **HTML** ```html

``` Add the Javascript code to the same page: **JavaScript** ```javascript var element = document.querySelector("[rel=email-opt-in]") var options = { platform: "email", size: "large", // or `small` for a smaller form doubleOptIn: false, // or `true` to require double opt-in, after configuring your opt-in message i18n: { en: { terms: 'By checking this box, I agree that [COMPANY NAME] can be in touch with me by email to provide [insert purpose of communications - e.g. updates and marketing offers]. I understand that I can change my mind and opt out at any time by clicking the unsubscribe link in the footer of any email I receive from [COMPANY], or by contacting [email address]. I understand that I do not need to provide consent to these messages as a condition for any purchase. I understand that my information will be used as described here and in compliance with the privacy policy.', footer: 'Our Terms of Service are available here.' } } } UA.then(function (sdk) { return sdk.plugins.load("subscription-form", "https://aswpsdkus.com/notify/v1/ua-subscription-form.min.js") }).then(function (formFactory) { formFactory.embedForm(element, options) }) ``` For more detailed examples of both email and SMS forms and a reference of available options and methods for your form, see [Opt-in Forms](https://www.airship.com/docs/developer/sdk-integration/web/plugins/opt-in-forms/) in our Web SDK plugins documentation. # SMS keywords > {{< glossary_definition "sms_keyword" >}} Use keywords to: * Opt users in to messaging campaigns based on their keyword-indicated interests. * Drive loyalty with unique keywords for loyalty members and non-members. * Trigger external processes, e.g., a chatbot, using webhooks. * Provide directions or access to promotional information, coupons, etc. * Target future messaging based on keyword generated tags or subscription lists. You can define opt-in keywords that will opt the user in to receiving SMS notifications or trigger opt-in flows. By default, users can text any of these words to opt out of notifications: `STOP`, `STOPALL`, `UNSUBSCRIBE`, `CANCEL`, `END`, `QUIT`, `ARRET`. You can also add additional opt-out keywords. See: [Opt-In/Out Handling](https://www.airship.com/docs/developer/api-integrations/sms/opt-in-out-handling/). Mobile-originated messages are represented as [Events](https://www.airship.com/docs/reference/glossary/#events). Each event records the keywords that your audience uses and additional identifying information. You can use these events to observe opt-in and opt-out trends in [Performance Analytics](https://www.airship.com/docs/reference/glossary/#pa) or to get events directly from [Real-Time Data Streaming](https://www.airship.com/docs/reference/glossary/#rtds). > **Important:** Before implementing changes to compliance keywords (e.g., HELP and STOP), please consult your legal counsel in order to address your specific use case or regulatory requirements in your jurisdiction. Certain compliance keywords may be required in certain jurisdictions or under the local carrier requirements. ## Keyword format When you create a keyword, you must configure the following: * **Keyword** — The word that triggers the response text and opt-in action, e.g., `JOIN` or `YES`. * Must be unique per sender ID * 100 characters maximum * Cannot contain spaces * Case insensitive * **Response** — The text that is sent to a user when they reply with the keyword or alias. You can select a pre-configured [webhook](https://www.airship.com/docs/developer/api-integrations/sms/inbound-message-handling/) as an alternative or in addition to the response text. * **Sender** — A [Sender ID](https://www.airship.com/docs/reference/glossary/#sender_id). **You must have at least one sender ID configured in your project before you can create keywords.** You can also configure these options: * **Alias** — Alternatives to the keyword. Must be unique per sender ID. Aliases have the same formatting requirements and restrictions as keywords. * **Opt-in action** — The event that occurs when a user replies with the keyword or alias: *None*, *Opt in*, *Opt out*, or *Create channel without opting in*. * **Tags** — Add or remove [Tags](https://www.airship.com/docs/reference/glossary/#tag) when a user replies with the keyword or alias. * **Shorten links** — When enabled, if your response includes URLs (beginning with `http://` or `https://`), they will be converted to [shortened links](https://www.airship.com/docs/reference/glossary/#sms_link_shortening). * **Subscription lists** — Opt a user in to or out of [Subscription Lists](https://www.airship.com/docs/reference/glossary/#subscription_list). See: [Subscription List Opt In/Out](#opt-in). * **Webhook** — You can select a pre-configured [webhook](https://www.airship.com/docs/developer/api-integrations/sms/inbound-message-handling/) as an alternative or in addition to the response text. ## Create keywords 1. Go to **Messages**, then **SMS Keywords**. 1. Select **+** in the map or **+ Create new keyword**. 1. Enter the keyword and aliases. Click **Add** after entering each alias. 1. Click *Keyword action →* or select the *Response* card in the map. 1. Enter the response text. You can leave this field empty if you are configuring a webhook instead. 1. Configure options: * *Shorten links* — Toggle to enable. * *Opt-in action* — Make a selection. * *Webhook* — Make a selection. A selection is required if you are omitting response text. * *Tags* — Select *Add* or *Remove*, enter a tag name in the search field, then: * If searching for an **existing tag**, click to select from the search results. Search for existing tags returns all custom tag groups that contain that tag. * If creating a **new tag**, click **Create new tag: [search term]**, enter a [custom tag group](https://www.airship.com/docs/guides/audience/tags/#custom-tag-groups) name in the search field that appears, then click to to select from the search results. * *Subscription lists* — Select *Opt in to* or *Opt out of*, search for a subscription list and select from the results. Repeat for multiple lists. 1. Click **Settings** and select a sender ID. Each sender ID in the list is prepended with its country. 1. Click **Save** and confirm. ## Manage keywords To view the list of the keywords in your project, go to **Messages**, then **SMS Keywords**. * Keywords are grouped by sender ID. * Sender IDs are sorted numerically then alphabetically. Keywords are sorted by creation order. * You can filter the list by searching for keyword, alias, or sender ID. You can edit all fields and selections in an existing keyword: 1. Select a keyword from the list. 1. Make your changes. 1. Click **Save** and confirm. To delete a keyword: 1. Select a keyword from the list. 1. Click **Settings**. 1. Click **Delete keyword** and confirm. # Media library > Store and manage image, audio, and video content for your messages. You can preview each file and assign keywords so they are easily found in search. ## About the media library Use the media library to host media files for your project and insert them when you compose messages, without uploading the same asset every time. Your Airship plan must include [CDN](https://en.wikipedia.org/wiki/Content_delivery_network) support to use the media library. [Contact Support](https://support.airship.com/) if you are interested in enabling CDN media hosting. File guidelines and handling: * Uploaded media must be 2 MB or smaller. * You can upload up to 100 files at a time. * There are no restrictions on uploading identical files or files with identical names. * The media library is not available for MMS messages. * Media that is not accessed by end users is automatically removed according to the [Airship Data Retention Schedule](https://www.airship.com/docs/reference/general/#data-retention-schedule). See also [Media guidelines](https://www.airship.com/docs/reference/messages/media-guidelines/). ## Add media to the library To add media to your project: 1. Go to **Content** and select **Media** 1. Select **Upload media** and choose your files. ## Insert media in message content You can access the library when inserting media in messages: 1. (For a media field in a message) Select **Upload**, then **Insert media**. 1. (From layouts in the [Interactive Editor](https://www.airship.com/docs/reference/glossary/#interactive_editor)) Select an Image element in the message, then select **Upload image**. 1. (From the [Native Experience AI Agent](https://www.airship.com/docs/guides/messaging/editors/native/ai-content/)) Select the upload icon (paperclip), then **Select from the media library**. 1. Manage your media files as needed. You cannot select multiple files when in this view. 1. To add media to the message, select a file, then **Insert selected media**. ## Managing media Go to **Content** and select **Media** to access your media library. Your most recent upload is listed first. You can sort the list by file name, size, or date uploaded, filter by keyword, and search by name or keyword. In the list, select a file name to open a drawer where you can do the following: * Preview the media. For audio and video files, you can play the file from the preview. * Edit the keywords. Select **Save** after making your changes. * Select **Duplicate**, which is the same as the action available from the more menu icon (⋯), as described in the table below. * View the date and time when the item was uploaded. To edit the keywords for multiple files: 1. Select the files in the list to open the details drawer. You can use the arrows below the preview to navigate between files. 1. Under **Shared Keywords**, add or remove keywords. 1. Select **Save**. The following actions are available from the more menu icon (⋯) in the media list: | Action | Description | Steps | | --- | --- | --- | | **Duplicate** | Save a copy of the file to a different project. The copy will have the same keywords as the original. | Select the more menu icon (⋯) for a file, then **Duplicate**. Search for the project name you'd like to save to, then select **Duplicate**. | | **View information and access additional actions** | Open the same drawer as when you select a file name. For what you can do in the drawer, see the list above this table. | Select the more menu icon (⋯), then **View detail**. | | **Delete** | Remove a file from your media library. | Select the more menu icon (⋯), then **Delete**. | # Composer Favorites > {{< glossary_definition "composer_favorites" >}} * Quickly send **time-sensitive messages**. * Reduce **campaign setup time**. * Maintain **quality control** — Protect message content or settings that should *not* be altered — you can choose which step to start the new message from, and steps prior to that will not be accessible. Composer Favorites are set per project, not for individual Airship users. ## Creating Composer Favorites You can create up to 100 Composer Favorites. From your project dashboard: 1. Select the **Create** dropdown menu (▼), then select **Message**. 1. Compose your message, making selections and filling in content. 1. When you are ready to save the current state, select the favorite icon (★). Be sure to select the icon within the Message composer, not the one in the header that is for [dashboard Favorites](https://www.airship.com/docs/guides/getting-started/ui/dashboard/#searching-and-favorites). 1. Enter a name and description. 1. Select the composer step to start from using the Favorite to create a new message. You cannot change this setting later. > **Important:** When creating a message using the Composer Favorite: > * Any step prior to the starting point step selected here will not be accessible. > * If you select immediate delivery (Send Now) for the Favorite and also select Audience or Content as the starting point step, the Delivery step will not be accessible. 1. Select **Save and exit**. ## Using Composer Favorites You can access Composer Favorites from the Create menu or from your project settings. When you create a new message from a Favorite, any additions or changes apply to the new message only. They are not saved for the Favorite. Access Favorites from the Create menu: 1. Select **Create**. 1. Under **Composer Favorites**, select from your three most recently created, modified, or used Favorites, or select **View all** and select a Favorite. 1. Complete the remaining composer steps. Access Favorites from your project settings: 1. Next to your project name, select the dropdown menu (▼), then **Settings**. 1. Under **Project settings**, select **Composer Favorites**. 1. Select **Create message** for a Favorite. 1. Complete the remaining composer steps. ## Managing Composer Favorites To access all the Favorites in your project: 1. Next to your project name, select the dropdown menu (▼), then **Settings**. 1. Under **Project settings**, select **Composer Favorites**. Each Favorite is listed with its name, description, the date when it was last modified, and the username of the team member who performed the modification. The list is sorted by last modified date, with the latest date first. A count of your current number of favorites is at the bottom right corner of the screen. Options: | Option | Behavior | Steps | | --- | --- | --- | | **Edit the Audience, Content, and/or Delivery** | Your changes are saved automatically as you edit. You will see "Favorite updated just now" in the bottom left corner of the screen. You can revert to the version when it last saved. | Select the edit icon ( ) for a Favorite and make your changes. To revert, select the down arrow icon (▼), then **Revert**. | | **Edit the name, description, or starting point** | You must manually save your changes. | Select the edit icon ( ) for a favorite, then select the down arrow icon (▼), then **Save changes**. Make your changes, then select **Save and exit**. | | **Duplicate** | A copy of the favorite is added your project. You can set its name, description, or starting point before or after saving. | Select the edit icon ( ) for a favorite, then select the down arrow icon (▼), then **Make a copy...**. Edit the name, description, or starting point and/or select **Save and exit**. | | **Delete** | The Favorite is removed from your project immediately. | Select the delete icon (trash) for a Favorite. |