콘텐츠로 건너뛰기

네이티브 인앱 템플릿 구문

네이티브 인앱은 SDK에서 직접 렌더링됩니다. WebView는 사용되지 않습니다. ZIP 리소스는 index.html 페이지 대신 메시지를 구조화된 데이터(레이아웃 유형, 텍스트, 색상, 이미지, 버튼)로 설명하는 native-config.json 파일을 포함합니다. SDK는 이 파일을 읽고 일치하는 네이티브 뷰를 그리므로, 내장된 웹 페이지보다 더 부드러운 애니메이션과 더 나은 성능을 제공합니다.

이 가이드는 native-config.json 스키마(각 표시 유형에 대한 필드, 유형 및 예제)를 설명합니다. 기존의 HTML 기반 형식에 대해서는 리치 미디어 템플릿 구문을 참조하세요.

전제 조건

Anchor link to

네이티브 인앱에는 다음이 필요합니다:

  • iOS: SDK 7.2.0 이상 (배너, 캐러셀, 시트는 7.2.1 이상)
  • Android: SDK 6.10.0 이상 (배너, 캐러셀, 시트는 6.10.1 이상)

모든 표시 유형이 두 플랫폼에서 아직 사용 가능한 것은 아닙니다. 특정 형식에 의존하기 전에 플랫폼 지원을 확인하세요.

플랫폼 지원

Anchor link to
표시 유형
iOS
Android
modal✅ 7.2.0+✅ 6.10.0+
fullscreen✅ 7.2.0+✅ 6.10.0+
stories✅ 7.2.0+✅ 6.10.0+
banner✅ 7.2.1+✅ 6.10.1+
carousel✅ 7.2.1+✅ 6.10.1+
sheet✅ 7.2.1+✅ 6.10.1+
video아직 사용할 수 없음
pip아직 사용할 수 없음
scratchcard아직 사용할 수 없음
spinwheel아직 사용할 수 없음

템플릿 구조

Anchor link to

네이티브 인앱 템플릿은 일반 리치 미디어 템플릿과 동일한 ZIP 아카이브이지만, 루트에 index.html 대신 native-config.json 파일이 포함되어 있습니다:

<template>.zip
├── native-config.json ← 필수, 레이아웃 및 콘텐츠
├── pushwoosh.json ← 선택 사항, 현지화 (아래 참조)

native-config.json에서 참조되는 이미지 및 비디오(pip/videoimage, poster, fallback, url)는 절대 HTTPS URL이어야 합니다. SDK는 네트워크를 통해 이를 로드합니다. 아카이브에서 로컬 파일을 읽지 않습니다.

구성 자체는 단일 JSON 객체입니다:

{ "displayType": "<type>", "<type>": { /* 이 유형에 대한 콘텐츠 블록 */ } }

displayType은 아래의 10가지 형식 중 하나를 선택합니다. 일치하는 키 아래의 객체는 해당 형식의 콘텐츠를 보유합니다. 알 수 없는 displayType이 있거나, 콘텐츠 블록이 없거나, 필수 목록(carousel/storiesitems, spinwheelsegments)이 비어 있는 구성은 유효하지 않습니다. SDK는 깨진 레이아웃을 렌더링하는 대신 표시를 건너뜁니다.

전송 설정(시작/종료 날짜 및 빈도 제한)은 native-config.json의 일부가 아닙니다. 다른 모든 인앱과 동일하게 캠페인의 표시 설정 단계에서 구성됩니다.

빈도 제한은 네이티브 인앱에 적용되려면 명시적인 SDK 측 옵트인이 추가로 필요합니다. SDK 통합을 참조하세요.

모든 색상 값은 CSS 16진수 문자열입니다: #RGB, #RGBA, #RRGGBB 또는 #RRGGBBAA. 네 가지 형식 모두 앞에 #가 필요합니다.

공유 구성 요소

Anchor link to

이러한 작은 객체들은 여러 표시 유형에서 재사용됩니다.

필드유형필수설명
textstring텍스트 내용
colorstring텍스트 색상
{ "text": "Spin for a garage perk", "color": "#FFFFFFFF" }
필드유형필수설명
colorstring테두리 색상
radiusnumber모서리 반경 (포인트 단위)
{ "color": "#0E72E5FF", "radius": 12 }

배경색 위에 선택적으로 표시되는 이미지입니다. fullscreenscratchcard에서 사용됩니다.

필드유형필수설명
imagestring아니요커버 이미지 URL
backgroundstring이미지 아래(또는 대신) 표시되는 배경색
{ "image": "https://example.com/cover.jpg", "background": "#1A1A1EFF" }

type에 따른 구별된 유니온:

변형필드설명
{ "type": "close" }없음인앱을 닫습니다
{ "type": "url", "url": string }url 필수URL 또는 딥 링크를 엽니다
{ "type": "url", "url": "pushwoosh://sale" }
필드유형필수설명
textText버튼 레이블
backgroundstring버튼 채우기 색상
borderBorder버튼 테두리
actionAction탭 시 실행되는 액션

spinButton(spinwheel) 및 revealButton(scratchcard)은 action 없이 동일한 형태를 사용합니다. 해당 동작(휠 돌리기, 카드 공개)은 내장되어 있습니다.

{
"text": { "text": "Book a test drive", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}

scratchcardspinwheel에 의해 표시되는 상품 패널입니다. 유효한 보상에는 title 또는 code가 있습니다.

필드유형필수설명
titleText아니요보상 헤드라인
messageText아니요보상 설명
codestring아니요복사 버튼과 함께 렌더링되는 프로모션 코드
buttonButton아니요자체 액션이 있는 확인 버튼
{
"title": { "text": "20% off detailing", "color": "#111111FF" },
"message": { "text": "Valid for any full-detail booking this month.", "color": "#555555FF" },
"code": "APEX20",
"button": {
"text": { "text": "Book detailing", "color": "#FFFFFFFF" },
"background": "#B3227CFF",
"border": { "color": "#B3227CFF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://detailing" }
}
}

표시 유형

Anchor link to

화면의 상단 또는 하단 가장자리에 고정된 작은 바입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
positiontop | bottom화면 가장자리
backgroundstring바 배경색
imagestring아니요왼쪽에 썸네일
titleText아니요한 줄 제목, 줄임표로 잘림
messageText아니요본문 텍스트, 최대 2줄
actionAction바 자체를 탭했을 때 실행됨
autoDismissnumber아니요이 시간(초) 후에 자동 닫기. 닫힐 때까지 유지하려면 생략
{
"displayType": "banner",
"banner": {
"showClose": true,
"position": "bottom",
"background": "#4B5057FF",
"image": "https://example.com/thumb.jpg",
"title": { "text": "Alpine A110 just dropped", "color": "#FFFFFFFF" },
"message": { "text": "The featherweight icon — tap to see the build", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/x6f" },
"autoDismiss": 6
}
}

페이지 표시 점이 있는 전체 화면의 스와이프 가능한 카드 세트입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
itemsItem[]카드 (최소 1개)

캐러셀 아이템:

필드유형필수설명
titleText아니요카드 제목
messageText아니요카드 부제목
imagestring아니요카드 이미지
actionAction아니요카드를 탭했을 때 실행됨
{
"displayType": "carousel",
"carousel": {
"showClose": true,
"items": [
{
"image": "https://example.com/card-1.jpg",
"title": { "text": "AMG GT R", "color": "#FFFFFFFF" },
"message": { "text": "585 hp biturbo V8 — just landed", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/n6fx" }
},
{
"image": "https://example.com/card-2.jpg",
"title": { "text": "Alpine A110", "color": "#FFFFFFFF" },
"message": { "text": "Featherweight icon — limited allocation", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/x6f" }
}
]
}
}

fullscreen

Anchor link to

가장자리까지 꽉 찬 커버 이미지 위에 텍스트와 버튼이 있습니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
coverCover배경 이미지 및 색상
titleText아니요제목
messageText아니요본문 텍스트
buttonsButton[]하단의 버튼 (비어 있을 수 있음)
{
"displayType": "fullscreen",
"fullscreen": {
"showClose": true,
"cover": { "image": "https://example.com/hero.jpg", "background": "#1A1A1EFF" },
"title": { "text": "Pure Maranello", "color": "#FFFFFFFF" },
"message": { "text": "The prancing horse, reimagined.", "color": "#EBEBEBFF" },
"buttons": [
{
"text": { "text": "Reserve now", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 8 },
"action": { "type": "url", "url": "pushwoosh://sale" }
},
{
"text": { "text": "Not now", "color": "#FFFFFFFF" },
"background": "#00000000",
"border": { "color": "#FFFFFF99", "radius": 8 },
"action": { "type": "close" }
}
]
}
}

중앙에 위치한 카드입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
dimBackgroundboolean카드 뒤의 화면을 어둡게 함
backgroundstring카드 배경색
imagestring아니요커버 이미지
titleText아니요제목
messageText아니요본문 텍스트
buttonsButton[]텍스트 아래의 버튼 (비어 있을 수 있음)
{
"displayType": "modal",
"modal": {
"showClose": true,
"dimBackground": true,
"background": "#FFFFFFFF",
"image": "https://example.com/cover.jpg",
"title": { "text": "The GT R has landed", "color": "#4B5057FF" },
"message": { "text": "585 hp — now in the showroom.", "color": "#4B5057FF" },
"buttons": [
{
"text": { "text": "Book a test drive", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
},
{
"text": { "text": "Not now", "color": "#4B5057FF" },
"background": "#FFFFFFFF",
"border": { "color": "#4B5057FF", "radius": 12 },
"action": { "type": "close" }
}
]
}
}

화면 모서리에 고정된 플로팅 PIP(Picture-in-Picture) 비디오 창입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
positionbottom-right | bottom-left | top-right | top-left화면 모서리
loopboolean재생 반복
mutedboolean음소거 상태로 시작
urlstring비디오 URL
posterstring아니요재생 시작 전에 표시되는 포스터
fallbackstring아니요비디오 재생 실패 시 표시되는 이미지
widthnumber화면 너비에 대한 창 너비 백분율, 15-70으로 제한됨
aspectRationumber창의 높이 대 너비 비율
borderRadiusnumber아니요창 모서리 반경 (포인트 단위)
actionAction아니요창 자체를 탭했을 때 실행됨

pip에는 구성 가능한 버튼이 없습니다. 창 컨트롤(전체 화면으로 확장, 음소거, 닫기)은 시스템에서 제공됩니다.

{
"displayType": "pip",
"pip": {
"showClose": true,
"position": "bottom-right",
"loop": true,
"muted": true,
"url": "https://example.com/teaser.mp4",
"poster": "https://example.com/poster.jpg",
"width": 40,
"aspectRatio": 0.5625,
"action": { "type": "url", "url": "pushwoosh://product/x6f" }
}
}

scratchcard

Anchor link to

긁을 수 있는 포일 레이어 아래에 보상이 숨겨진 카드입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
backgroundstring | string[]카드 배경색 또는 그라데이션 정지점
revealThresholdnumber보상이 공개되기 전에 긁어야 하는 포일의 비율 (0-1)
coverCover포일 레이어. image가 없으면 배경색 위에 “여기를 긁으세요” 힌트가 표시됨
revealButtonButton (no action)아니요”즉시 공개” 버튼
titleText아니요제목
messageText아니요본문 텍스트
rewardReward포일 아래에 숨겨진 상품
{
"displayType": "scratchcard",
"scratchcard": {
"showClose": true,
"background": ["#3A1C71FF", "#B3227CFF", "#E0503AFF"],
"revealThreshold": 0.55,
"cover": { "background": "#C9CDD6FF" },
"revealButton": {
"text": { "text": "Reveal without scratching", "color": "#3A1C71FF" },
"background": "#F2DFF5FF",
"border": { "color": "#F2DFF5FF", "radius": 10 }
},
"title": { "text": "Your loyalty reward", "color": "#FFFFFFFF" },
"message": { "text": "Scratch the foil to reveal this week's garage perk.", "color": "#F2DFF5FF" },
"reward": {
"title": { "text": "20% off detailing", "color": "#111111FF" },
"message": { "text": "Valid for any full-detail booking this month.", "color": "#555555FF" },
"code": "APEX20",
"button": {
"text": { "text": "Book detailing", "color": "#FFFFFFFF" },
"background": "#B3227CFF",
"border": { "color": "#B3227CFF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://detailing" }
}
}
}
}

드래그 핸들이 있는 하단 가장자리에 고정된 카드입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
dimBackgroundboolean시트 뒤의 화면을 어둡게 함
backgroundstring시트 배경색
imagestring아니요커버 이미지
titleText아니요제목
messageText아니요본문 텍스트
buttonsButton[]텍스트 아래의 버튼 (비어 있을 수 있음)
{
"displayType": "sheet",
"sheet": {
"showClose": true,
"dimBackground": true,
"background": "#FFFFFFFF",
"image": "https://example.com/cover.jpg",
"title": { "text": "Your quote is ready", "color": "#000000FF" },
"message": { "text": "Guaranteed buyout for your A110: $68,500.", "color": "#000000FF" },
"buttons": [
{
"text": { "text": "Get guaranteed quote", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}
]
}
}

가중치가 적용된 세그먼트와 중앙 허브 버튼이 있는 행운의 룰렛입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
backgroundstring | string[]카드 배경색 또는 그라데이션 정지점
winIndexnumber당첨 세그먼트의 인덱스 (0부터 시작)
spinButtonButton (no action)중앙 허브 버튼
titleText아니요제목
messageText아니요본문 텍스트
rewardReward당첨 스핀에 대한 보상 (자체 보상이 없는 세그먼트의 대체)
loseTitleText아니요패배 시 표시되는 헤드라인
segmentsSegment[]휠 세그먼트 (SDK는 2-12개를 예상)

세그먼트:

필드유형필수설명
messageText세그먼트 레이블
colorstring아니요세그먼트 색상. 휠 주위에 적용되는 대체 팔레트를 사용하려면 생략
weightnumber상대적인 세그먼트 크기
rewardReward아니요세그먼트별 보상
{
"displayType": "spinwheel",
"spinwheel": {
"showClose": true,
"background": ["#1B1B46FF", "#5B2B8FFF", "#B0338AFF"],
"winIndex": 1,
"spinButton": {
"text": { "text": "SPIN", "color": "#1B1B46FF" },
"background": "#F2C94CFF",
"border": { "color": "#D9A02BFF", "radius": 36 }
},
"title": { "text": "Spin for a garage perk", "color": "#FFFFFFFF" },
"message": { "text": "One spin — every slice wins this week.", "color": "#E3D9F2FF" },
"reward": {
"title": { "text": "You won a garage perk!", "color": "#FFFFFFFF" },
"code": "APEXPERK",
"button": {
"text": { "text": "Claim", "color": "#FFFFFFFF" },
"background": "#5B2B8FFF",
"border": { "color": "#5B2B8FFF", "radius": 12 },
"action": { "type": "close" }
}
},
"segments": [
{ "message": { "text": "5% off", "color": "#FFFFFFFF" }, "color": "#5856D6FF", "weight": 1 },
{
"message": { "text": "20% off", "color": "#FFFFFFFF" },
"color": "#30B0C7FF",
"weight": 1,
"reward": {
"title": { "text": "20% off your next service", "color": "#FFFFFFFF" },
"code": "SPIN20",
"button": {
"text": { "text": "Claim service deal", "color": "#FFFFFFFF" },
"background": "#30B0C7FF",
"border": { "color": "#30B0C7FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://service" }
}
}
},
{ "message": { "text": "Free wash", "color": "#FFFFFFFF" }, "color": "#FF2D55FF", "weight": 1 }
]
}
}

소셜 미디어 스토리와 유사하게 상단에 진행률 표시줄이 있는 전체 화면 슬라이드입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
loopboolean마지막 슬라이드 후 첫 번째 슬라이드부터 다시 시작
itemsItem[]슬라이드 (최소 1개)

스토리 아이템:

필드유형필수설명
titleText아니요제목
messageText아니요부제목
imagestring아니요슬라이드 배경 이미지
buttonsButton[]하단의 CTA 버튼 (비어 있을 수 있음)
durationnumber슬라이드 지속 시간 (초)
{
"displayType": "stories",
"stories": {
"showClose": true,
"loop": false,
"items": [
{
"image": "https://example.com/slide-1.jpg",
"title": { "text": "AMG GT R", "color": "#FFFFFFFF" },
"message": { "text": "The Green Hell special", "color": "#FFFFFFFF" },
"buttons": [
{
"text": { "text": "Configure yours", "color": "#FFFFFFFF" },
"background": "#0F0F0FFF",
"border": { "color": "#0F0F0FFF", "radius": 26 },
"action": { "type": "url", "url": "pushwoosh://product/n6fx" }
}
],
"duration": 4
},
{
"image": "https://example.com/slide-2.jpg",
"title": { "text": "Alpine A110", "color": "#FFFFFFFF" },
"message": { "text": "The featherweight legend, reborn", "color": "#FFFFFFFF" },
"buttons": [],
"duration": 4
}
]
}
}

텍스트와 버튼이 위에 있는 전체 화면 비디오입니다.

필드유형필수설명
showCloseboolean닫기(✕) 버튼 표시
loopboolean재생 반복
mutedboolean음소거 상태로 시작
urlstring비디오 URL (HLS 또는 MP4)
posterstring아니요재생 시작 전에 표시되는 포스터
fallbackstring아니요비디오 재생 실패 시 표시되는 이미지
titleText아니요제목
messageText아니요본문 텍스트
buttonsButton[]하단의 CTA 버튼 (비어 있을 수 있음)
{
"displayType": "video",
"video": {
"showClose": true,
"loop": true,
"muted": true,
"url": "https://example.com/reveal.mp4",
"poster": "https://example.com/poster.jpg",
"title": { "text": "The reveal", "color": "#FFFFFFFF" },
"message": { "text": "Watch it move before anyone else.", "color": "#EBEBEBFF" },
"buttons": [
{
"text": { "text": "Shop the lineup", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 14 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}
]
}
}

네이티브 인앱은 HTML 리치 미디어와 정확히 동일한 현지화 메커니즘을 재사용합니다: native-config.json의 문자열 값은 {{key|type|default}} 플레이스홀더를 가질 수 있으며, 번역은 pushwoosh.json 추가하기에 설명된 것과 동일한 형식으로 옆에 있는 pushwoosh.json 파일에 저장됩니다. 플레이스홀더는 모든 깊이의 문자열 필드(제목, 버튼 레이블, 이미지 URL, 액션 URL)에 나타날 수 있습니다.

동적 콘텐츠

Anchor link to

텍스트 필드 — title, message, 버튼 text, reward.title/reward.message, 그리고 아이템/세그먼트 message — 는 푸시 및 이메일 콘텐츠에 사용되는 것과 동일한 {Tag|modifier|default} 약어 및 {% %}/{{ }} Liquid 태그인 동적 콘텐츠Liquid 구문도 허용합니다. Pushwoosh는 푸시 및 이메일과 동일한 방식으로 메시지를 보내기 전에 수신자별로 이를 확인합니다.

Control Panel 네이티브 인앱 편집기에서 템플릿을 빌드할 때, 삽입된 토큰은 실시간 미리보기에 칩으로 렌더링되며, 텍스트 필드의 Liquid가 구문 분석되지 않으면 저장이 차단됩니다.

SDK 통합

Anchor link to

앱에 네이티브 인앱 SDK 모듈을 추가하면 메시지가 자동으로 표시됩니다. 푸시, Customer Journey, postEvent 또는 받은 편지함에 의해 트리거된 메시지를 표시하기 위해 추가 코드가 필요하지 않습니다.

SDK는 또한 수동 제어를 위한 작은 API를 제공합니다:

  • iOS: Pushwoosh.inApp (모듈 PushwooshInApp)
  • Android: PushwooshInAppUi (모듈 pushwoosh-inapp-ui)
기능iOSAndroid
구성 직접 표시 (테스트/수동 사용)Pushwoosh.inApp.present(config)PushwooshInAppUi.present(configJson)
라이프사이클 및 클릭 관찰delegate (PWInAppMessageDelegate)delegate (InAppMessageDelegate)
화면에 무언가 있는지 확인isPresentingisPresenting
현재 표시된 것 닫기dismiss()dismiss()
표시 일시 중지 / 재개isPausedisPaused
maxDisplays / cooldown 제한 적용setFrequencyCapEnabled(_:)setFrequencyCapEnabled(...)

Delegate 콜백(모두 메인 스레드에서 실행됨): shouldDisplay(예: 결제 화면에서 메시지가 표시되기 전에 하나를 표시하지 않으려면 false 반환), willPresent, didPresent, didClose, clickedAction(url 액션을 탭할 때 URL이 열리기 전에 실행됨).

iOS는 또한 게임화된 scratchcardspinwheel 템플릿에 대해 rewardRevealedrewardClaimed를 보고합니다.

// iOS
Pushwoosh.inApp.delegate = self
Pushwoosh.inApp.setFrequencyCapEnabled(true)
// Android
PushwooshInAppUi.delegate = this
PushwooshInAppUi.setFrequencyCapEnabled(true)