콘텐츠로 건너뛰기

Pushwoosh InboxKit iOS 설정

iOS SDK 7.0.40부터 사용 가능합니다.

Pushwoosh InboxKit은 기존 받은 편지함 백엔드 위에 최신 UIKit 받은 편지함 화면을 제공합니다. 6개의 기본 셀 레이아웃은 간단한 배너부터 이미지 캐러셀, 인라인 비디오, Apple Wallet 패스에 이르기까지 일반적인 콘텐츠 카드 형태를 다룹니다. 인라인 CTA 버튼은 가장 일반적인 상호 작용을 처리하며, 맞춤형 디자인이 필요한 경우 전체 영역을 서브클래싱할 수 있습니다.

배너, 캡션, 클래식, 캐러셀, 비디오 및 Apple Wallet 카드를 보여주는 InboxKit 피드

배너, 캡션, 클래식, 캐러셀, 비디오, Apple Wallet 카드가 포함된 기본 InboxKit 피드입니다.

InboxKit 사용 시기

Anchor link to

새로운 iOS 통합에는 InboxKit을 사용하세요. 이전 Objective-C PushwooshInboxUI 모듈을 대체하는 권장 모듈입니다.

InboxKit은 다음을 제공합니다:

  • 6가지 내장 셀 유형 — 배너, 캡션, 클래식, 캐러셀, 비디오, Apple Wallet — 페이로드의 displayType을 통해 메시지별로 선택하거나, attributes.forceCellKind를 통해 코드에서 강제할 수 있습니다. 전체 목록은 카드 유형을 참조하세요. (Apple Wallet 카드는 iOS 전용입니다.)
  • 타입이 지정된 PushwooshInboxButtonAction 열거형(openURL, dismiss, markRead, custom)을 사용하는 인라인 CTA 버튼. SDK는 처음 세 가지를 자동으로 처리하고, custom은 델리게이트가 자체 로직으로 라우팅합니다.
  • 고정 지원: actionParams["pinned"] == true인 메시지는 피드 상단에 고정되고 핀 글리프를 렌더링합니다.
  • 스와이프하여 삭제, 당겨서 새로고침, 사라질 때 자동으로 읽음으로 표시 — 모두 PushwooshInboxKitAttributes를 통해 토글할 수 있습니다.
  • 영구 저장소: 네트워크 호출이 아직 확인되지 않았더라도 삭제 및 읽음 상태는 프로세스 재시작 후에도 유지됩니다.
  • 완전히 맞춤형 레이아웃을 위한 개방형 PushwooshInboxCell 기본 클래스.

서버 계약은 변경되지 않았습니다 — 동일한 Pushwoosh 받은 편지함 백엔드, 페이로드 및 대시보드 도구가 이전과 동일하게 작동합니다.

통합 방법 선택

Anchor link to

카드 유형

Anchor link to

InboxKit은 메시지별로 셀 레이아웃을 선택합니다. 기본 리졸버는 푸시 페이로드에서 displayType을 읽습니다 — SDK가 actionParams 아래에 전달하는 data 객체 내에 넣으세요. displayType이 없으면 리졸버는 휴리스틱으로 대체됩니다: 이미지 + 제목 없음 → 배너, 이미지 + 제목 → 캡션, 그 외에는 클래식. 코드에서 전체 피드에 대해 하나의 레이아웃을 강제하려면 attributes.forceCellKind를 설정하세요.

각 리치 레이아웃은 정상적으로 성능이 저하됩니다: 필요한 페이로드가 없거나 형식이 잘못된 경우, 카드는 빈 플레이스홀더를 렌더링하는 대신 classic으로 대체됩니다 (그리고 WARN이 기록됩니다).

displayType레이아웃필수 페이로드 필드성능 저하 시
banner전체 이미지, 텍스트 없음이미지 (inbox_image 또는 data.image)이미지가 없을 때 classic
captioned상단에 이미지, 하단에 제목 + 본문이미지 (inbox_image 또는 data.image)이미지가 없을 때 classic
classic색상 있는 이니셜 아바타 + 제목 + 본문
carousel스와이프 가능한 다중 이미지 갤러리data.carousel (슬라이드 배열)슬라이드가 없을 때 classic
video재생 배지가 있는 포스터, 탭 시 전체 화면 플레이어data.video (url + 선택적 poster)디스크립터가 없을 때 classic
wallet”Apple Wallet에 추가” 버튼 (iOS 전용)data.wallet (.pkpass URL)패스 URL이 없을 때 classic
InboxKit 배너 카드
배너 카드
InboxKit 캡션 카드
캡션 카드
InboxKit 클래식 카드
클래식 카드
InboxKit 캐러셀 카드
캐러셀 카드
InboxKit 비디오 카드
비디오 카드
InboxKit Apple Wallet 카드
Apple Wallet 카드

배너, 캡션, 클래식 카드는 표준 메시지 필드(이미지, 제목, 본문)와 선택적인 buttons 배열에 의해 구동됩니다 — 인라인 CTA 버튼 추가를 참조하세요. 캐러셀, 비디오, Apple Wallet 카드는 아래에 설명된 data 내부에 추가 구조화된 데이터를 포함합니다.

캐러셀 카드

Anchor link to

캐러셀은 단일 메시지에서 여러 이미지를 렌더링합니다 — 슬라이드별 캡션과 탭 대상이 선택적인 스와이프 가능한 갤러리입니다. 슬라이드는 data.carousel에 있습니다. 각 슬라이드에는 image가 필요하며, title(캡션 오버레이)과 url(탭 시 열리는 딥 링크)은 선택 사항입니다. 이미지가 없는 슬라이드는 삭제되고, url이 없는 슬라이드를 탭하면 메시지의 기본 행 작업으로 대체됩니다.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "New arrivals",
"content": "Swipe through this week's drops",
"inbox_days": 7,
"data": {
"displayType": "carousel",
"carousel": [
{ "image": "https://cdn.example.com/inbox/1.jpg", "title": "New in", "url": "myapp://product/1" },
{ "image": "https://cdn.example.com/inbox/2.jpg", "title": "On sale", "url": "myapp://product/2" },
{ "image": "https://cdn.example.com/inbox/3.jpg" }
]
},
"platforms": [1]
}]
}
}

비디오 카드

Anchor link to

비디오 카드는 재생 배지가 있는 포스터 이미지를 보여줍니다. 탭하면 전체 화면 플레이어가 열립니다(무음 스위치가 켜져 있어도 소리가 켜짐). 디스크립터는 data.video에 있습니다: url은 필수이며 http/https 스트림 또는 파일이어야 합니다. poster는 선택적 미리보기 이미지입니다.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Watch the reveal",
"content": "Tap to play",
"inbox_days": 7,
"data": {
"displayType": "video",
"video": {
"url": "https://cdn.example.com/inbox/clip.mp4",
"poster": "https://cdn.example.com/inbox/poster.jpg"
}
},
"platforms": [1]
}]
}
}

Apple Wallet 카드

Anchor link to

Apple Wallet 카드는 공식 Apple Wallet에 추가 버튼 위에 선택적 히어로 이미지, 제목, 본문을 표시합니다. 버튼을 탭하면 .pkpass가 다운로드되고 시스템 패스 추가 시트가 표시됩니다. 이를 사용하여 받은 편지함에서 직접 쿠폰, 멤버십 카드, 티켓 또는 탑승권을 전달할 수 있습니다. 이 카드는 iOS / Mac Catalyst 전용이며, 다른 플랫폼에서는 메시지가 클래식 카드로 렌더링됩니다.

패스 URL은 data.wallet에 있으며, 일반 문자열 또는 pass 필드가 있는 객체로 존재합니다. 선택적 data.image는 히어로 이미지를 추가합니다. 패스 URL이 없거나 기기에서 패스를 추가할 수 없는 경우 버튼은 자동으로 숨겨집니다.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Your loyalty card is ready",
"content": "Add it to Apple Wallet in one tap",
"inbox_days": 7,
"data": {
"displayType": "wallet",
"image": "https://cdn.example.com/inbox/loyalty.png",
"wallet": "https://passes.example.com/v1/passes/pass.com.example.loyalty/abc123?token=…"
},
"platforms": [1]
}]
}
}

결과는 델리게이트에 보고됩니다:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didAddWalletPassFor message: PWInboxMessageProtocol) {
// 패스가 이제 사용자의 Wallet에 있습니다 — 원한다면 확인 메시지를 표시하세요.
}
func inboxKit(_ vc: PushwooshInboxKitViewController,
didFailToAddWalletPassFor message: PWInboxMessageProtocol,
error: Error?) {
// 다운로드 실패 — 재시도, 로그 등을 표시하세요.
}
}

두 콜백 모두 선택 사항입니다(기본 빈 구현을 가짐). 사용자가 시스템 시트를 취소하는 것은 성공도 실패도 아니므로, 이 경우 콜백이 실행되지 않습니다.

InboxKit 셀은 기본적으로 VoiceOver를 지원합니다. 배너, 캡션, 클래식 카드는 기본 레이블을 통해 제목, 본문, 날짜를 노출하며, 인라인 CTA 버튼은 자체 제목을 읽습니다. 리치 카드는 명시적인 시맨틱을 추가합니다:

  • 비디오 — 포스터는 “비디오 재생”이라는 레이블이 붙은 단일 버튼 요소로 노출됩니다(.button + .startsMediaSession 특성). 따라서 VoiceOver는 이를 일반 이미지가 아닌 미디어 컨트롤로 알립니다.
  • 캐러셀 — 각 슬라이드는 접근성 레이블이 슬라이드의 캡션이거나, 캡션이 없을 경우 “슬라이드”인 버튼 요소입니다. 페이지 표시기는 현재 위치를 “총 개수n번째”로 알립니다.
  • Apple WalletApple Wallet에 추가 버튼은 Apple의 표준 PKAddPassButton이며, 자체적으로 현지화된 VoiceOver 레이블을 가집니다.

UI 테스트 및 자동화를 위해 두 개의 안정적인 accessibilityIdentifier가 설정됩니다: 비디오 포스터에는 inboxkit.video.play, Wallet 버튼에는 inboxkit.wallet.add가 설정됩니다.

메시지에서 사용자 지정 데이터 읽기

Anchor link to

푸시가 받은 편지함에 나타나게 하려면 Messages API createMessage 요청에 inbox_image, inbox_date 또는 inbox_days가 포함되어야 합니다 — 이 필드 중 하나가 없으면 푸시는 일반 알림으로 전달되고 받은 편지함 피드에 도달하지 않습니다. 자유 형식의 사용자 지정 데이터는 data 키 아래에 있으며, SDK는 이를 클라이언트에 u 매개변수로 전달합니다:

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Summer sale",
"content": "30% off everything — limited time only",
"inbox_image": "https://cdn.example.com/inbox/summer.png",
"inbox_days": 7,
"data": {
"displayType": "captioned",
"promo_id": "SUMMER2026",
"screen": "promo_details"
},
"platforms": [1]
}]
}
}

SDK는 해당 객체를 actionParams를 통해 받은 편지함 메시지에 노출합니다. 사용자가 행이나 인라인 CTA를 탭할 때 델리게이트에서 이를 읽으세요:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didSelect message: PWInboxMessageProtocol) -> Bool {
guard let params = message.actionParams as? [String: Any] else { return true }
// 사용자 지정 `data` 객체는 "u" 키 아래에 도착합니다 —
// 중첩된 딕셔너리 또는 JSON으로 인코딩된 문자열로,
// 페이로드가 업스트림에서 어떻게 빌드되었는지에 따라 다릅니다.
let custom: [String: Any]? = {
if let dict = params["u"] as? [String: Any] { return dict }
if let raw = params["u"] as? String,
let bytes = raw.data(using: .utf8),
let parsed = try? JSONSerialization.jsonObject(with: bytes) as? [String: Any] {
return parsed
}
return nil
}()
if let promoId = custom?["promo_id"] as? String {
navigateToPromo(promoId)
return false // 탭을 처리했으므로 SDK는 기본 작업을 실행해서는 안 됩니다
}
return true
}
}

동일한 actionParams["u"] 조회는 인라인 CTA 버튼에 대해 inboxKit(_:didTapButton:onMessage:) 내에서 작동합니다. 타입이 지정된 CTA 경우(openURL, dismiss, markRead)에 대해 SDK는 이미 기본 작업을 수행합니다 — 해당 동작을 유지하려면 true를 반환하고, 이를 억제하고 자체적으로 실행하려면 false를 반환하세요.

인라인 CTA 버튼 추가

Anchor link to

메시지는 최대 3개의 인라인 콜투액션 버튼을 가질 수 있습니다. 버튼은 data 내의 다른 사용자 지정 데이터와 함께 buttons 배열로 존재합니다. SDK는 캡션 및 클래식 셀 내에서 자동으로 렌더링합니다:

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "New promo card",
"content": "Tap a button to claim or save",
"inbox_image": "https://cdn.example.com/inbox/promo.png",
"inbox_days": 7,
"data": {
"displayType": "captioned",
"promo_id": "SUMMER2026",
"buttons": [
{ "title": "Claim", "url": "https://example.com/promo/SUMMER2026" },
{ "title": "Read", "action": "markRead" },
{ "title": "Save", "action": "custom", "tag": "save_promo" }
]
},
"platforms": [1]
}]
}
}

각 버튼 객체에는 다음 필드가 있습니다:

필드유형설명
titlestring필수. 보이는 버튼 레이블.
urlstring비어 있지 않고 파싱 가능한 URL은 openURL 작업을 생성합니다. 델리게이트가 이를 억제하지 않는 한 SDK는 UIApplication.shared.open을 통해 엽니다.
actionstring명시적 작업 토큰: dismiss(피드에서 메시지 제거), markRead(메시지를 읽음으로 표시) 또는 custom(호스트 처리). 대소문자를 구분하지 않습니다.
기타anyactioncustom일 때, titleaction을 제외한 버튼 객체의 모든 키는 사용자 지정 페이로드로 델리게이트에 전달됩니다 — 마케터와 키(예: tag)에 대해 합의하고 이를 기반으로 디스패치하세요.

해결 우선순위: 명시적 action 토큰이 먼저, 그 다음 비어 있지 않은 경우 url, 그렇지 않으면 버튼은 전체 페이로드(titleaction 제외)를 전달하는 custom으로 대체됩니다.

델리게이트에서 탭을 가로챕니다. button.action 속성은 타입이 지정된 PushwooshInboxButtonAction 열거형입니다:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didTapButton button: PushwooshInboxButton,
onMessage message: PWInboxMessageProtocol) -> Bool {
switch button.action {
case .openURL(let url):
// 기본 동작이 괜찮습니다 — SDK가 URL을 열도록 합니다.
return true
case .dismiss, .markRead:
// SDK가 둘 다 처리합니다. 재정의하려면 false를 반환하세요.
return true
case .custom(let payload):
// 마케터가 정의한 사용자 지정 버튼. 합의한 키를 기반으로 디스패치하세요.
if let tag = payload["tag"] as? String {
switch tag {
case "save_promo":
saveCurrentPromoLocally(message: message)
default:
break
}
}
return true // custom의 경우 무시됩니다 — SDK는 여기서 기본 작업을 실행하지 않습니다
}
}
}