콘텐츠로 건너뛰기

네이티브 인앱 템플릿 구문

네이티브 인앱은 SDK에서 직접 렌더링됩니다. WebView는 사용되지 않습니다. index.html 페이지 대신, ZIP 리소스는 메시지를 구조화된 데이터(레이아웃 유형, 텍스트, 색상, 이미지, 버튼)로 설명하는 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✅✅ 6.11.0+
pip✅아직 사용 불가
scratchcard✅아직 사용 불가
spinwheel✅아직 사용 불가

템플릿 구조

Anchor link to

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

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

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

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

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

displayType은 아래의 10가지 형식 중 하나를 선택합니다. 일치하는 키 아래의 객체는 해당 형식의 콘텐츠를 담고 있습니다. 알 수 없는 displayType, 누락된 콘텐츠 블록 또는 비어 있는 필수 목록(carousel/stories의 items, spinwheel의 segments)이 있는 구성은 유효하지 않습니다. 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 }

배경색 위에 표시되는 선택적 이미지입니다. fullscreen 및 scratchcard에서 사용됩니다.

필드유형필수설명
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" }
}

scratchcard 및 spinwheel에서 표시되는 상품 패널입니다. 유효한 보상에는 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)는 동적 콘텐츠 및 Liquid 구문도 허용합니다. 이는 푸시 및 이메일 콘텐츠에 사용되는 것과 동일한 {Tag|modifier|default} 약식 및 {% %}/{{ }} 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(...)

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

iOS는 추가적으로 게임화된 scratchcard 및 spinwheel 템플릿에 대해 rewardRevealed 및 rewardClaimed를 보고합니다.

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