오퍼 작업하기

텐투플레이에서 오퍼란 일종의 구매 추천 시스템으로서 플레이어의 게임 효율과 사용자 경험을 향상시키는 목적으로 사용됩니다. 오퍼 사용에 필요한 두 가지 작업이 있는데 하나는 오퍼 데이터 가져오기이고 다른 하나는 오퍼 메시지에 대한 반응 업데이트하기입니다. 이 두 가지 작업에 대한 방법을 알아보겠습니다.

이후 설명은 다음과 같은 가정 하에 진행됩니다.

  • 오퍼 생성에 필요한 모든 행동 데이터를 업로드하였다.

  • REST API 통신은 두 서버 간에 이루어진다. 즉, 텐투플레이 서버로 요청하는 주체는 게임 클라이언트가 아닌 게임 서버이다. 게임 클라이언트 프로그램을 통해 요청하고 싶다면 텐투플레이 디스코드를 통해 문의해 주세요.

TentuPlay REST use offer ko
오퍼 작업 개요

오퍼 데이터 가져오기

일단 사용자 행동 데이터가 업로드되면 텐투플레이 서버는 정기적으로 이를 분석하고 향후 요청 시 애널리틱스나 오퍼용으로 사용될 수 있도록 분석된 데이터를 보관해 둡니다. 이에 첫번째로 해야할 일은 텐투플레이 서버에 있는 오퍼 데이터를 가져오는 작업입니다. 서버에 가져온 오퍼 데이터로 오퍼 메시지를 만들 수 있습니다.

요청

GET https://api.tentuplay.io/v2021.4/offers HTTP/1.1
Content-Type:application/json

헤더

이름 자료형 필수여부 기본값

TPAuthMode

api_key_plain

string

필수

null

TPClientKey

Client key

string

필수

null

TPPlayerId

Target player’s uuid

string

필수

null

요청

성공

HTTP/1.1 200 OK
Content-Type:application/json
Body 예시
{
  "status": 200,
  "reason": "OK",
  "data": [
    {
      "offer_id": 2,
      "player_slug": "TentuPlayer",
      "offer":
        "{
            \"offer_type\": \"ai\",
            \"is_offer_active\": true,
            \"recommendations\": [
                {
                  \"store\": \"ios\",
                  \"product_list\": [
                    {
                      \"end_datetime\": null,
                      \"product_index\": \"00000\",
                      \"purchase_link\": \"https://tentuplay.io/\",
                      \"start_datetime\": null,
                      \"purchasable_slug\": \"BombBow\"
                    }
                  ]
                }
            ],
            \"display_parameters\":
              {
                \"en\":
                  {
                    \"title\": \"A Special Recommendation For EXPLOSIVE Growth!\",
                    \"message\": \"Congratulations on reaching <color=#FFD84F>explosive growth!</color>\\n In 3 days you earned 1000 coins,\\n and reached level 7!\\n If you buy the following product, you can grow more efficiently.\",
                    \"background_url\": \"https://tentuplay-static.s3.ap-northeast-2.amazonaws.com/black_background.png\",
                    \"toggle_message\": \"Don't Show Again Today\"
                  },
                \"ko\":
                  {
                    \"title\": \"폭풍성장 플레이어를 위한 특별한 정보!\",
                    \"message\": \"<color=#FFD84F>폭풍성장</color> 등급 달성을 축하합니다.\\n 3일 동안 코인을 1000만큼 획득하고,\\n 7레벨 성장하셨습니다!\\n 다음의 상품을 구매하면 효율을 더욱 높일 수 있습니다.\",
                    \"background_url\": \"https://tentuplay-static.s3.ap-northeast-2.amazonaws.com/black_background.png\",
                    \"toggle_message\": \"오늘 다시보지 않기\"
                  }
              }
        }",
      "create_datetime": "2021-11-08 06:36:07",
      "valid_until": null,
      "valid_for": null,
      "valid_open_count": null,
      "first_opened_at": null,
      "is_offer_active": 1
    },
    {
      "offer_id": 1,
      "player_slug": "TentuPlayer",
      "offer":
        "{
            \"price\": 99.99,
            \"message\":
              {
                \"en\":
                  {
                    \"url\": \"https://tentuplay.io/en/\",
                    \"image\": \"https://tentuplay-static.s3.ap-northeast-2.amazonaws.com/offer_demo_image_landscape.png\",
                    \"title\": \"english campaign\"
                  },
                \"ko\":
                  {
                    \"url\": \"https://tentuplay.io/ko/\",
                    \"image\": \"https://tentuplay-static.s3.ap-northeast-2.amazonaws.com/offer_demo_image_landscape.png\",
                    \"title\": \"한글 캠페인\"
                  }
              },
            \"product_id\": null,
            \"product_name\": null,
            \"discount_rate\": 10,
            \"discount_price\": 89.99,
            \"message_layout\": \"h\"
        }",
      "create_datetime": "2021-11-08 06:36:07",
      "valid_until": null,
      "valid_for": null,
      "valid_open_count": null,
      "first_opened_at": null,
      "is_offer_active": 1
    }
  ]
}

오퍼 구현하기

오퍼 요청에 대한 응답을 받으면 먼저 오퍼 데이터의 유효성을 확인하고 그 다음 수신인에게 전달할 오퍼 메시지를 생성해야 합니다. 다음은 이전 섹션의 응답 body 예시를 기준으로 한 설명입니다.

오퍼 유효성 검증

오퍼를 올바르게 사용하려면 다음 표에 있는 항목들을 점검해야 합니다.

구성요소 설명 비고

공통

offer_type

is_offer_active

is_offer_activetrue이거나 1인 오퍼만 사용하십시오

first_opened_at

오퍼를 처음 열어본 시간을 나타냅니다. 이 값이 null이라면 이는 오퍼가 개봉된 적이 없거나 해당 속성이 업데이트된 적이 없음을 의미합니다.

valid_until, valid_for, first_opened_at

오퍼의 유효 기간을 산정하는 데 사용됩니다.

create_datetime

UTC 기준으로 오퍼가 생성된 시간을 나타냅니다.

recommendations
(AI 오퍼만 해당)

start_datetime, end_datetime

해당 상품이 판매 중임을 확인하는데 사용됩니다.

AI 오퍼의 값들은 상품 정보 파일을 업로드했을 경우에만 생성됩니다.

product_index, purchasable_slug

이 값들 중 하나를 이용해 플레이어가 해당 상품을 구입할 수 있는지 확인합니다.

store

store의 값을 보고 플레이어 디바이스 OS에서 실행되는 오퍼를 구현합니다.

오퍼 만들기

이제 오퍼의 body 콘텐츠를 파싱하여 이를 오퍼의 GUI(graphical user interface)에 넣음으로써 사용자가 오퍼와의 상호작용을 통해 오퍼를 소비할 수 있도록 합니다.

본 단계는 오퍼를 표현하기 위해 메시지 창이나 본문 필드, 기타 화면 제어 요소(예: 버튼, 체크 박스)들로 구성된 GUI를 이미 구현했다는 가정하에 진행됩니다. 참고로 유니티 SDK에는 오퍼 메시지를 생성하기 위한 기본 UI 템플릿이 제공되고 있습니다(AI 오퍼 템플릿, 개인화 오퍼 템플릿).

AI 인게임 상점 오퍼 만들기

  1. 화면 표시 콘텐츠(display_parameters 아래 title, messeage, background_url, toggle_message)를 언어별로 UI에 배치합니다.

  2. 상품 정보(recommendations 아래 product_index, purchasable_slug, purchase_link)를 오퍼에 추가하여 사용자가 오퍼 메시지에 소개된 추천 상품을 구입할 수 있도록 합니다. (유니티 SDK에서의 해당 설명)

개인화 오퍼 만들기

  1. message_layout의 값을 보고 페이지 방향을 정합니다. (h: 가로, v: 세로).

  2. 화면 표시 콘텐츠(message 아래 title, url, image)를 언어별로 UI에 배치합니다.

오퍼 상태 업데이트하기

오퍼에 어떤 이벤트가 발생하면 오퍼의 상태 변화를 서버에 반영해 주어야 합니다. 오퍼 상태 업데이트는 다음과 같은 이벤트 발생시 필요합니다.

  • 사용자에게 전달할 오퍼를 서버에서 가져왔을 때

  • 사용자가 오퍼에 어떤 반응을 하였을 때 (예: 열기, 무시하기, 다음 단계로 진행하기)

오퍼가 노출되었을 때

먼저 서버에 오퍼 요청 후 이를 성공적으로 받았음을 알려주어야 합니다. 이 때 오퍼의 상태는 "impress"로 바뀝니다.

요청

POST https://api.tentuplay.io/v2021.4/logs HTTP/1.1
Content-Type:application/json
헤더
이름 자료형 필수여부 기본값

TPAuthMode

api_key_plain

string

필수

null

TPClientKey

Client key

string

필수

null

Body
Body 예시
{
  "players_offers": [
    {
      "player_slug": "TentuPlayer",
      "offer_id": 999,
			"message_status": "impress",
			"message_detail": "this_purchasable_slug",
      "event_timestamp": 1647504609
    }
  ],
  ...
}
Body 파라미터
이름 설명 자료형 필수여부 비고

player_slug

플레이어의 고유 ID

string

필수

Unity SDK의 player_uuid와 동일

offer_id

오퍼의 고유 ID

int

필수

message_status

오퍼에 발생한 이벤트

  • impress: 오퍼를 성공적으로 가져옴

  • open: 플레이어가 오퍼를 열어봄

  • dismiss: 플레이어가 오퍼 UI의 닫기 버튼을 클릭함

  • interact: 플레이어가 구매와 같은 관련 버튼을 클릭하여 다음 단계로 넘어감

string

필수

message_detail

오퍼에서 광고 관련 인게임 콘텐츠의 고유 ID (예: 광고된 인게임 아이템, DLC 상품, 인게임 기프트 카드)

string

선택

event_timestamp

UTC 기준 유닉스 시간

int

필수

오퍼가 소비되었을 때

생성된 오퍼 메시지는 미리 정의된 조건이 충족되면 대상 사용자에게 전송됩니다. 오퍼 메시지가 성공적으로 사용자에게 전달되면 사용자는 이 메시지를 열어보거나 그냥 무시하는 등의 반응을 보일 수 있습니다. 이러한 상호 작용으로 오퍼 메시지의 상태가 바뀔 수 있는데 만약 변경이 발생했다면 이를 서버에 있는 동일한 메시지 상태에도 이를 반영해 줘야 합니다. 이제 오퍼 메시지의 리소스 상태도 업데이트되었으므로 오퍼 성과에 대한 지표도 따라서 업데이트됩니다.

오퍼 최초 개봉 시 업데이트

사용자가 처음으로 오퍼를 열어보게 되면 해당 이벤트를 발생 시간과 함께 서버에 알려야 합니다. 이로써 서버의 first_opened_at 속성에 시간 값이 들어갑니다. 이 값은 주로 오퍼의 유효 시간을 계산하는데 사용됩니다.

요청 형식
POST https://api.tentuplay.io/v2021.4/offers HTTP/1.1
Content-Type:application/json
요청 헤더
이름 자료형 필수여부 비고

TPAuthMode

api_key_plain

string

필수

TPClientKey

Client key

string

필수

TPOfferId

오퍼 ID

int

필수

TPPlayerId

플레이어 ID

string

필수

TPOpenedAt

오퍼 최초 개봉 시 타임 스탬프

string

필수

예: 2022-08-19 13:32:08

개봉된 적이 없는 어떤 오퍼(즉, first_opened_at값이 null인 오퍼)를 가져온 후 first_opened_at값을 업데이트했다면 그 오퍼를 서버에서 다시 받아와야 합니다.

오퍼 소비 시 업데이트

텐투플레이에서는 오퍼와의 상호 작용을 아래와 같이 세가지 유형으로 구분하고 있으며 이는 message_status의 값이 됩니다.

  • open: 플레이어가 오퍼를 열어봄

  • dismiss: 플레이어가 오퍼 UI의 닫기 버튼을 클릭함

  • interact: 플레이어가 구매와 같은 관련 버튼을 클릭하여 다음 단계로 넘어감

요청 형식
POST https://api.tentuplay.io/v2021.4/logs HTTP/1.1
Content-Type:application/json
요청 헤더
이름 자료형 필수여부 기본값

TPAuthMode

api_key_plain

string

필수

null

TPClientKey

Client key

string

필수

null

Body 예시
  • Open

  • Dismiss

  • Interact

{
  "players_offers": [
    {
      "player_slug": "TentuPlayer",
      "offer_id": 999,
			"message_status": "open",
			"message_detail": "this_purchasable_slug",
      "event_timestamp": 1647504609
    }
  ],
  ...
}
{
  "players_offers": [
    {
      "player_slug": "TentuPlayer",
      "offer_id": 999,
			"message_status": "dismiss",
			"message_detail": "this_purchasable_slug",
      "event_timestamp": 1647504609
    }
  ],
  ...
}
{
  "players_offers": [
    {
      "player_slug": "TentuPlayer",
      "offer_id": 999,
			"message_status": "interact",
			"message_detail": "this_purchasable_slug",
      "event_timestamp": 1647504609
    }
  ],
  ...
}
오퍼 상태 업데이트에 대한 샘플 코드
  • Open

  • Dismiss

  • Interact

TPStashEvent myStashEvent = new TPStashEvent();
myStashEvent.StashOfferEvent(
	player_uuid: player_id, offer_id: thisOffer.offer_id,
	message_status: messageStatus.Open, message_detail: purchasable_slug);

myPerOffer.OfferOpened(thisOffer.offer_id, (response) =>
        {
        });
int r = new TPStashEvent().StashOfferEvent(
		player_uuid: thisPlayerUUID, offer_id: thisOffer.offer_id, message_status: messageStatus.Dismiss,
		message_detail: purchasable_slug);
new TPUploadData().UploadData(toCheckInterval: false);
int r = new TPStashEvent().StashOfferEvent(
		player_uuid: thisPlayerUUID, offer_id: thisOffer.offer_id, message_status: messageStatus.Interact,
	  message_detail: purchasable_slug);
new TPUploadData().UploadData(toCheckInterval: false);