iOS Embedded Content
Embedded Content is an alternative Scene format that can be displayed on any app or web screen in a view defined by a developer. It can also be presented in Story format. iOS SDK 18.7+
About Embedded Content
Present the content of a SceneA single or multi-screen in-app experience cached on users’ devices and displayed when users meet certain conditions in your app or website, such as viewing a particular screen or when a Custom Event occurs. They can be presented in fullscreen, modal, or embedded format using the default swipe/click mode or as a Story. Scenes can also contain survey questions. on any app screen. There are three primary components:
Component | Description |
---|---|
A "view" in your app where the content will display | An app developer creates an AirshipEmbeddedView that controls the dimensions of the content and its location in your app. They also determine what content can be displayed in the view by setting a value for the view's embeddedId that matches the ID of an Embedded Content view style. |
A view style in your project settings | A marketer creates an Embedded Content view style and assigns an ID for reference in the app view's embeddedId . |
A Scene using an Embedded Content view style | This is the source of the content that will be displayed in the view. |
Once the Scene is triggered for display and matches the specified audience conditions, its content is available to users when visiting a screen that contains the AirshipEmbeddedView
.
The view is populated with the content from all active Scenes with the matching ID, sorted based on priority. When an embedded view loads content, the highest priority Scene that is queued for display will be shown. The same content will be shown across app and web sessions until it is dismissed by the user or is no longer available. The view will then show the next Scene with the highest priority from the display queue.
Airship first prepares the content when the triggering event occurs and then refreshes it upon every app open or web session start. This ensures that users always experience the most up-to-date message. So, after updating active Embedded Content, users will see the latest version the next time they open the app or load the app or web page containing the view.
Embedded Content behavior is the same as In-App AutomationsMessages cached on users’ devices and displayed when users meet certain conditions within your app, such as viewing a particular screen or opening the app a certain number of times. and modal and fullscreen Scenes:
- The content displays only within the app.
- When the app is terminated, the content is not automatically dismissed. It continues to display in the next app session.
If you are not already on iOS SDK 18.7+, see the Airship iOS SDK 17.x to 18.0 migration guide .
Adding an AirshipEmbeddedView
The AirshipEmbeddedView
is a SwiftUI view that defines a place for an Airship Embedded Content to be displayed. When defining an AirshipEmbeddedView
, specify the embeddedId
for the content it should display. The value of the embeddedId
must be the ID of an Embedded Content view style in your project.
// Show any "home_banner" Embedded Content
AirshipEmbeddedView(embeddedID: "home_banner")
Placeholders
If content is unavailable to display, the default behavior is to show an EmptyView
. You can customize this by providing a placeholder.
AirshipEmbeddedView(embeddedID: "home_banner") {
Text("Placeholder!")
}
Placing in a ScrollView
When placed directly in a ScrollView
, or a child view within the ScrollView
that is allowed to grow unbounded in the scrollable direction, you need to pass the maximum size of the embedded view to make percent-based sizing work correctly. The easiest way is to wrap the ScrollView
in a GeometryReader
and pass the size info to the embedded view.
struct ScrollViewExample: View {
var body: some View {
GeometryReader { geometryProxy in
ScrollView(showsIndicators: false) {
AirshipEmbeddedView(
embeddedID: "home_banner",
embeddedSize: AirshipEmbeddedSize(
parentBounds: geometryProxy.size
)
)
}
}
}
}
When using a GeometryReader
, it takes up as much space as allowed. To avoid this and instead measure the current size of the content, you can use the view extension airshipMeasureView
.
struct ScrollViewExample: View {
@State var state: CGSize?
var body: some View {
ScrollView(showsIndicators: false) {
AirshipEmbeddedView(
embeddedID: "home_banner",
embeddedSize: AirshipEmbeddedSize(
maxWidth: state?.width,
maxHeight: state?.height
)
)
}
.airshipMeasureView(self.$state)
}
}
Styling
You can set a custom style on the embedded view, which allows you to modify how the content is displayed or what pending content is displayed.
In this example, the embedded view has a Dismiss Button above it:
public struct CustomEmbeddedViewStyle: AirshipEmbeddedViewStyle {
@ViewBuilder
public func makeBody(configuration: AirshipEmbeddedViewStyleConfiguration) -> some View {
if let view = configuration.views.first {
VStack {
Button("Dismiss") {
view.dismiss()
}
view
}
} else {
configuration.placeHolder
}
}
}
AirshipEmbeddedView(embeddedID: "home_banner")
.setAirshipEmbeddedStyle(CustomEmbeddedViewStyle())
iOS 14 and iOS 15 support
AirshipEmbeddedView
takes advantage of custom SwiftUI layouts to properly size
itself based on the bounds of the view. The Layout
protocol is only available for iOS 16+. AirshipEmbeddedView
will still work on older iOS versions, but you must provide the parent’s bounds to enable properly sizing
itself:
AirshipEmbeddedView(
embeddedID: "home_banner",
embeddedSize: AirshipEmbeddedSize(
parentBounds: CGSize(100, 200)
)
)
Observing available Embedded Content
Embedded Content is not always available, and even after being triggered, it still needs to be prepared before it
can be displayed. An AirshipEmbeddedView
will automatically update when content is available and transition from
the placeholder to the content once content is available. If you need to query the availability of Embedded
Content, you can use an AirshipEmbeddedObserver
to watch for updates.
An AirshipEmbeddedObserver
is an ObservableObject
that you can use as a StateObject
to automatically refresh the view when new Embedded Content is available. It allows for more dynamic handling of Embedded Content than just content or a placeholder.
struct ObservableExample: View {
@StateObject
private var embeddedObserver: AirshipEmbeddedObserver = AirshipEmbeddedObserver(embeddedID: "home_banner")
@State var tabIndex = 0
var body: some View {
if (embeddedObserver.embeddedInfos.isEmpty) {
Text("No banner available")
} else {
Text("Banner available")
AirshipEmbeddedView(embeddedID: "home_banner")
}
}
}
The AirshipEmbeddedObserver
can be created to watch for one embeddedID
, all embedded IDs, or use custom filtering for embedded IDs. The embeddedInfos
is the FIFO order of embedded info, including the extras you can set through the Scene composer when creating the content.
Categories