요약: 본 기사는 플랫폼을 사용하는 광고주 또는 앱 소유자라고 하는 앱스플라이어 고객을 사용하여 앱 사용 및 어트리뷰션을 기록하는 것입니다. 앱 소유자는 OpenGDPR API를 구현하여 GDPR(유럽), CCPA(캘리포니아), LGPD(브라질) 및 PDPA(태국)와 같은 적용 가능한 데이터 보호법을 준수합니다.
앱스플라이어 법무팀 공지 사항: 여기에 언급된 것은 법률적인 조언입니다. 귀하의 정보와 편의를 위해 제공됩니다. 법률 및 기타 전문 고문과 긴밀히 협조하여 GDPR, CCPA 또는 기타 법률이 적용되거나 적용되지 않을 수 있는 방법을 정확하게 판별해야 합니다. 사용자와 앱스플라이어간의 프라이버시 관계는 앱스플라이어 서비스 개인정보 보호 정책에 의해 관리됩니다. 이 서비스 개인정보 보호 정책과 관련된 질문 또는 데이터 보호 담당자에게 문의하려면 privacy@appsflyer.com로 메일을 보내 주십시오. 일반 데이터 보호 규정 27조의 경우 앱스플라이어의 EU 내 대리인은 AppsFlyer Germany GmbH Kurfürstendamm 11, c/o WeWork, 10719 Berlin, Germany(연락처 privacy@appsflyer.com;+49-30-3119-9129)로 연락하실 수 있습니다.
개인정보 보호 규정
본 기사에서 개인정보 보호정책에 대한 참조에는 다음 테이블에 기재한 규정이 포함됩니다.
규정 | 로고 | 설명 |
---|---|---|
GDPR | ![]() |
개인정보보호 규정(GDPR)은 유럽 연합(EU) 시민의 데이터 보호 및 개인정보보호에 관한 EU 규정입니다. |
CCPA | ![]() |
캘리포니아 소비자 프라이버시 보호법 |
LGPD | ![]() |
브라질 일반 개인정보 보호법 |
PDPA | ![]() |
개인 데이터 보호법 |
용어 프라이버시 규정, GDPR, CCPA, LGPD 및 PDPA는 본 기술자료에서 상호 교환 가능하게 사용됩니다.
OpenGDPR 이니셔티브
개인정보 보호 규정에 따라 제출된 데이터 주체별 요청을 처리하고 관리하기 위해 mParticle, Amplitude 및 Braze와 함께 앱스플라이어에서 OpenGDPR 프로토콜을 시작했습니다.
OpenGDPR은 오픈 소스 프레임워크로, 소비자 데이터의 공정하고 투명한 사용을 위해 기술 회사들 간의 협력을 지원합니다. 이 프로토콜을 사용하면 공급업체가 고객 데이터를 처리하고 저장하는 여러 시스템에서 데이터 정보 보호 작업을 수행할 수 있습니다.
이 이니셔티브에 대한 자세한 내용은 여기에서 확인할 수 있습니다.
정의
GDPR 용어 | 앱스플라이어 용어 | 설명 |
---|---|---|
데이터 주체 | 앱 사용자 또는 최종 사용자 | 데이터가 수집되는 앱 사용자 |
데이터 처리자 | 앱 소유자 또는 광고주 | 앱 소유자는 개인 데이터가 처리되는 목적 및 수단을 판별합니다. |
데이터 처리 수탁자 | 앱스플라이어 및 파트너 | AppsFlyer 및 관련 파트너가 데이터 처리자를 대신해 개인 데이터를 처리합니다. |
GDPR 요구 사항
GDPR은 데이터 처리자가 준수해야 하는 데이터 주체의 필수 권리를 자세히 규정합니다. API 목적상 이러한 권리는 요청 유형으로 변환됩니다. 아래에서 앱스플라이어가 다른 요청 유형을 처리하는 방법을 자세히 설명합니다.
요청 유형 (권리) |
GDPR 정의 |
앱스플라이어에서 요청 처리 |
---|---|---|
액세스 |
|
앱 소유자는 앱 사용자의 처리된 개인 데이터의 사본을 수신합니다. |
이동성 |
앱 사용자에게 제공되는 모든 개인 데이터는 CSV 파일처럼 흔히 사용되는, 기계로 판독 가능한 구조화된 형식이어야 합니다. |
앱 소유자는 앱 사용자의 처리된 개인 데이터의 사본을 수신합니다. |
정정 |
데이터가 정확하지 않거나 사실이 아닌 경우 앱 사용자에게 이를 정정할 수 있도록 허용합니다. 앱 소유자는 부정확하거나 불완전한 데이터를 지우거나 정정해야 합니다. |
|
삭제 |
삭제 권리에 따라 앱 소유자가 요청을 받은 날로부터 14일 이내에 개인 데이터를 제거해야 합니다. |
데이터를 삭제합니다. |
AppsFlyer의 GDPR 요청 API
본 절에 설명된 대로 GDPR 요청 API를 사용하여 GDPR 준수를 구현합니다.
- GDPR 요청: 열람, 이동, 삭제 또는 정정 중 하나의 요청을 수행합니다.
- 상태 요청: GDPR 요청의 현재 상태를 쿼리합니다.
- 검색 요청: 지원되는 API 버전 및 데이터 형식을 조회합니다.
- 취소: 승인 대기 단계에서 GDPR 요청을 취소합니다.
앱 소유자는 앱에 UI 변경을 구현하여 앱 사용자가 요청을 제출할 수 있도록 해야 합니다. GDPR 요청은 한 번에 한 사용자만 제출할 수 있습니다.
1. GDPR 요청
GDPR 요청 과정
GDPR 요청 유형인 열람, 이동, 삭제 및 정정 과정은 모두 동일합니다.
- 앱 사용자는 요청을 제출합니다.
- 앱 소유자는 GDPR 요청을 구성하고 (아래 참조) 앱스플라이어로 전송합니다.
- 앱스플라이어는 요청을 수신하고 유효한 요청에 대해 "201 OK"로 응답합니다.
- 다음 48시간 동안 요청이 큐에 대기되고 보류 중 상태가 됩니다. 앱 사용자는 요청을 취소할 수 있습니다.
- 48시간 후 요청 상태가 in_progress로 변경됩니다.앱스플라이어가 'status change' 포스트백을 보냅니다. 요청은 취소할 수 없습니다.
- a) 14일 이내에 앱스플라이어가 요청을 이행합니다.
삭제 또는 정정의 경우, 앱 사용자의 데이터가 삭제됩니다.
이식성 또는 액세스의 경우, 앱 사용자의 데이터는 GDPR 아래 또는 요청 API(아래 참조)를 통해 앱스플라이어 대시보드에서 액세스할 수 있습니다.
b) 요청 상태가 완료됨으로 갱신되었습니다.앱스플라이어가 status change 포스트백을 보냅니다.
GDPR 요청 형식
HTTP POST를 통해 GDPR 요청 API를 다음 엔드포인트로 제출할 수 있습니다.-
https://hq1.appsflyer.com/gdpr/opengdpr_requests?api_token=[api token]
API 토큰값은 Pull API에서 사용되는 API 토큰값과 같습니다. 관리자는 대시보드의 API 토큰 페이지에서 Pull API 토큰을 검색합니다.
속성 이름 | 필수적 | 설명 |
---|---|---|
subject_request_id | 예 | UUID v4 문자열입니다. 데이터 처리 수탁자에게 요청을 제출할 때 데이터 처리자가 생성합니다. 요청의 상태를 체크하고 요청을 업데이트 또는 취소하기 위해 사용할 수 있습니다. |
subject_request_type | 예 |
GDPR 요청 유형을 나타내는 문자열 값입니다. 지원 값:
|
subject_identities | 예 |
|
submitted_time | 예 |
|
property_id | 예 |
이 요청을 시도한 모바일 앱을 나타내는 문자열입니다. 예:
|
api_version | 아니요 | GDPR 요청 API의 알맞은 버전을 나타내는 버전 문자열 |
status_callback_urls | 예 |
|
오브젝트 유형 | 필수적 | 설명 |
---|---|---|
identity_type | 예 |
|
identity_value | 예 |
|
identity_format | 예 |
|
GDPR 삭제 요청 예시
curl --location --request POST 'https://hq1.appsflyer.com/gdpr/opengdpr_requests?api_token=[api_token]' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-raw '{
"subject_request_id":"f4e5a271-f25e-4107-b681-************",
"subject_request_type":"erasure",
"submitted_time":"2020-07-05T10:00:00Z",
"subject_identities":[
{
"identity_type":"android_advertising_id",
"identity_value":"55*****-****-****-************",
"identity_format":"raw"
}
],
"api_version":"0.1",
"property_id":"com.*********.*******.********",
"status_callback_urls":[
"https://examplecontroller.com/opengdpr_callbacks"
]
}'
GDPR 삭제 요청 코드 예시
/*
using the okhttp package install from maven
https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
*/
import okhttp3.*;
import java.io.IOException;
public class GdprSendRequest {
public static void main(String[] args){
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(null, "" +
"{\r\n\"subject_request_id\": \"<SUBJECT_ID>\"," +
"\r\n\"subject_request_type\": \"erasure\"," +
"\r\n\"submitted_time\": \"2018-11-02T15:00:00Z\"," +
"\r\n\"subject_identities\": [\r\n" +
"{\r\n\"identity_type\": \"android_advertising_id\"," +
"\r\n\"identity_value\": \"<ADVERTISING_ID>\"," +
"\r\n\"identity_format\": \"raw\"\r\n}" +
"\r\n]," +
"\r\n\"property_id\": \"com.example.application\"}");
Request request = new Request.Builder()
.url("https://hq1.appsflyer.com/gdpr/opengdpr_requests?api_token=<API_TOKEN>")
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
System.out.println(response.code());
System.out.println(response.body().string());
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}
""" using the requests python package,
install using pip install requests """
import requests
import json
headers = {
"Content-Type": "application/json",
"Accept": "application/json"
}
params = {
"api_token": ""
}
body = {
"subject_request_id": "",
"subject_request_type": "erasure",
"submitted_time": "2018-10-02T15:00:00Z",
"subject_identities": [
{ "identity_type": "android_advertising_id",
"identity_value": "",
"identity_format": "raw" }
],
"property_id": "com.example.application"
}
body = json.dumps(body)
res = requests.request("POST",
"https://hq1.appsflyer.com/gdpr/opengdpr_requests",
headers=headers, data=body, params=params)
print(res.text)
/* using the request npm package,
install using npm install request */
var request = require("request");
var options = { method: 'POST',
url: 'https://hq1.appsflyer.com/gdpr/opengdpr_requests',
qs: { api_token: '' },
headers:
{ Accept: 'application/json',
'Content-Type': 'application/json' },
body:
{ subject_request_id: '<SUBJECT_ID>',
subject_request_type: 'erasure',
submitted_time: '2018-10-02T15:00:00Z',
subject_identities:
[ { identity_type: 'android_advertising_id',
identity_value: '<ADVERTISING_ID>',
identity_format: 'raw' } ],
property_id: 'com.example.application'
},
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
using System;
using RestSharp;
namespace CS
{
class Gdpr
{
static void Main(string[] args)
{
var url = "https://hq1.appsflyer.com/gdpr/opengdpr_requests";
var apiToken = "?api_token=<API_TOKEN>";
var client = new RestClient(url + apiToken);
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
Request.AddHeader("Accept", "application/json");
var body = "{\r\n\"subject_request_id\": \"<SUBJECT_ID>\"," +
"\r\n \"subject_request_type\": \"erasure\"," +
"\r\n \"submitted_time\": \"2018-11-02T15:00:00Z\"," +
"\r\n \"subject_identities\": [\r\n" +
"{ \r\n \"identity_type\": \"android_advertising_id\"," +
"\r\n \"identity_value\": \"<ADVERTISING_ID>\"," +
"\r\n \"identity_format\": \"raw\"\r\n }" +
"\r\n ]," +
"\r\n \"property_id\": \"com.example.application\"}";
request.AddParameter("undefined", body,ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
// handle response by reading response.StatusCode
Console.WriteLine(response.Content);
}
}
}
2. 상태 요청
모든 제출된 GDPR 요청에 대해서 나중에 subject_request_id
를 지정하여 상태를 확인할 수 있습니다. 다음의 4가지 상태 유형이 있습니다.
- pending - 요청이 올바르게 수신되었고 현재 대기열에 있습니다.
- in_progress - 요청이 현재 처리 중입니다.
- completed - 요청이 처리되었습니다.
- canceled - 요청이 취소되었습니다.
상태 요청 형식
HTTP GET을 통해 상태 요청을 다음 엔드포인트로 제출할 수 있습니다.
https://hq1.appsflyer.com/gdpr/opengdpr_requests/[subject_request_id]?api_token=[api token]
상태 응답 예시
HTTP/1.1 200 OK
Content-Type: application/json
X-OpenGDPR-Processor Domain: example processor.com
X-OpenGDPR-Signature:
kiGlog3PdQx+FQmB8wYwFC1fekbJG7Dm9WdqgmXc9uKkFRSM4uPzylLi7j083461xLZ+mUloo3tpsmyIZpt5eMfgo7ejXPh6lqB4ZgCnN6+1b6Q3NoNcn/+11UOrvmDj772wvg6uIAFzsSVSjMQxRs8LAmHqFO4cF2pbuoPuK2diHOixxLj6+t97q0nZM7u3wmgkwF9EHIo3C6G1SI04/odvyY/VdMZgj3H1fLnz+X5rc42/wU4974u3iBrKgUnv0fcB4YB+L6Q3GsMbmYzuAbe0HpVA17ud/bVoyQZAkrW2yoSy1x4Ts6XKba6pLifIHf446Bubsf5r7x1kg6Eo7B8zur666NyWOYrglkOzU4IYO8ifJFRZZXazOgk7ggn9obEd78GBc3kjKKZdwaCrLx7WV5y9TMDCf+2FILOJM/MwTUy1dLZiaFHhGdzld2AjbjK1CfVzyPssch0iQYYtbR49GhumvkYl11S4oDfu0c3t/xUCZWg0hoR3XL3B7NjcrlrQinB1KbyTNZccKR0F4Lk9fDgwTVkrAg152UqPyzXxpdzXjfkDkSEgAevXQwVJWBNf18bMIEgdH2usF/XauQoyrne7rcMIWBISPgtBPj3mhcrwscjGVsxqJva8KCVCKD/4Axmo9DISib5/7A6uczJxQG2Bcrdj++vQqK2succ=
{
"controller_id":"example_controller_id",
"expected_completion_time":"2018-11-01T15:00:01Z",
"subject_request_id":"a7551968-d5d6-44b2-9831-815ac9017798",
"request_status":"pending",
"api_version":"0.1"
}
상태 포스트백
위의 GDPR 요청 흐름에서 설명한 바와 같이, GDPR 요청의 상태가 pending에서 in_progress로, 그리고 completed로 변경되는 경우, 앱스플라이어는 status_callback_urls 속성으로 지정된 요청 엔드포인트로 GDPR 포스트백을 전송합니다.
상태 포스트백 예시
POST /opengdpr_callbacks HTTP/1.1
Host: examplecontroller.com
Content-Type: application/json
X-OpenGDPR-Processor Domain: appsflyer.com
X-OpenGDPR-Signature: kiGlog3PdQx+FQmB8wYwFC1fekbJG7Dm9WdqgmXc9uKkFRSM4uPzylLi7j083461xLZ+mUloo3tpsmyIZpt5eMfgo7ejXPh6lqB4ZgCnN6+1b6Q3NoNcn/+11UOrvmDj772wvg6uIAFzsSVSjMQxRs8LAmHqFO4cF2pbuoPuK2diHOixxLj6+t97q0nZM7u3wmgkwF9EHIo3C6G1SI04/odvyY/VdMZgj3H1fLnz+X5rc42/wU4974u3iBrKgUnv0fcB4YB+L6Q3GsMbmYzuAbe0HpVA17ud/bVoyQZAkrW2yoSy1x4Ts6XKba6pLifIHf446Bubsf5r7x1kg6Eo7B8zur666NyWOYrglkOzU4IYO8ifJFRZZXazOgk7ggn9obEd78GBc3kjKKZdwaCrLx7WV5y9TMDCf+2FILOJM/MwTUy1dLZiaFHhGdzld2AjbjK1CfVzyPssch0iQYYtbR49GhumvkYl11S4oDfu0c3t/xUCZWg0hoR3XL3B7NjcrlrQinB1KbyTNZccKR0F4Lk9fDgwTVkrAg152UqPyzXxpdzXjfkDkSEgAevXQwVJWBNf18bMIEgdH2usF/XauQoyrne7rcMIWBISPgtBPj3mhcrwscjGVsxqJva8KCVCKD/4Axmo9DISib5/7A6uczJxQG2Bcrdj++vQqK2succ=
{
"controller_id":"example controller id at the processor",
"expected_completion_time":"2018-11-01T15:00:01Z",
"status_callback_url":"https://examplecontroller.com/opengdpr_callbacks",
"Subject_request_id":"a7551968-d5d6-44b2-9831-815ac9017798",
"Request_status":"pending"
}
3. 보고서 요청
열람 요청 또는 이동 요청이 완료되고 나면 보고서를 다음 엔드포인트로 HTTP GET을 활용하여 다운로드할 수 있습니다.
https://hq1.appsflyer.com/gdpr/download/[REQUEST_ID]?api_token=[TOKEN]
생성된 보고서는 완료 시점부터 14일간 다운로드할 수 있습니다.
4. 검색 요청
AppsFlyer가 지원하는 형식을 알아보기 위해 HTTP GET을 통한 검색 요청을 다음 엔드포인트로 제출할 수 있습니다.
https://hq1.appsflyer.com/gdpr/discovery?api_token=[api token]
검색 응답 예시
HTTP/1.1 200 OK
Content-Type: application/json
{
"api_version": "0.1",
"supported_identities": [
{
"identity_type": "android_advertising_id",
"identity_format": "raw"
},
],
"supported_subject_request_types": [
"erasure", "access", "portability", "rectification"
],
"processor_certificate": "https://exampleprocessor.com/cert.pem"
}
5. 취소 요청
subject_request_id
로 GDPR 요청을 취소할 수 있지만, 승인 대기 단계에서만 가능합니다.
subject_request_id
로 HTTP DELETE를 제출할 수 있습니다.
https://hq1.appsflyer.com/gdpr/opengdpr_requests/[subject_request_id]?api_token=[api token]
취소 응답
GDPR 취소 요청을 받으면 앱스플라이어는 상태 코드 202 및 기타 여러 파라미터와 함께 HTTP 응답을 반환합니다.
요청 취소가 이루어지면 앱스플라이어는 cancelled 상태의 포스트백을 전송합니다.
6. GDPR 요청 테스트 API
이 AppsFlyer API는 AppsFlyer의 GDPR 요청 API용 테스트 API입니다.
동작 방식
이 테스트 API가 동작하는 방식은 다음과 같습니다.
1. GDPR 요청이 생성되고 나면 요청이 즉시 승인 대기 상태로 변경됩니다. 테스트 목적으로 30초마다 상태가 변경됩니다.
2. 상태 포스트백의 엔드포인트가 GDPR 요청에 삽입된 경우 첫 번째 포스트백이 요청 직후에 전송되고 이후 상태 포스트백 두 개가 30초 간격으로 추가 전송됩니다.
GDPR 요청 테스트 엔드포인트
https://hq1.appsflyer.com/gdpr/stub?api_token=[api token]
상태 요청 테스트 엔드포인트
https://hq1.appsflyer.com/gdpr/stub/[request id]?api_token=[api token]
검색 요청 테스트 엔드포인트
https://hq1.appsflyer.com/gdpr/stub/discovery?api_token=[api token]
취소 요청 테스트 엔드포인트
https://hq1.appsflyer.com/gdpr/stub/[request id]?api_token=[api token]
참고
- 요청에 유효한 API 토큰이 포함되어 있어야 합니다.
- 'property_id' 속성에서 App ID는 계정 소유자(API 토큰에 따름)에 속해야 합니다.
7. 요청 로그
8. GDPR API 리턴 코드 및 오류 메시지
이 절에서는 GDPR API HTTP 리턴 코드 및 오류 메시지를 자세히 설명합니다.
리턴 코드 | 설명 |
---|---|
201 | 생성됨 |
202 | 취소 요청 수신함 |
400 |
잘못된 요청. 본문에는 다음 표에 나열된 오류 코드 및 메시지가 포함되어 있습니다. |
HTTP 리턴 코드 400-잘못된 요청
리턴 코드 400을 가진 메시지에는 오류 코드 및 메시지와 함께 JSON이 포함되어 있습니다.
{ "error":
{ "code":400, "af_gdpr_code": "%AF error code%", "message":"%error message text%"
}
}
오류 코드 |
오류 설명(메시지) |
---|---|
e111 | 속도 제한 초과 |
e211 | 잘못된 상태의 요청 취소 불가 |
e212 | 요청이 허용되지 않음. 식별자에 대한 삭제가 진행 중입니다. |
e213 | 요청이 이미 존재함 |
e214 | 요청을 찾을 수 없음 |
e311 | 잘못된 요청 콘텐츠-유형 |
e312 | 잘못된 API 버전 |
e313 | 잘못된 subject_request_id |
e314 | 잘못된 submitted_time 형식 |
e315 | 잘못된 status_callback_url 길이 |
e316 | 잘못된 status_callback_url 형식 |
e317 | 잘못된 app_id 형식 |
e318 | 잘못된 identity_type |
e319 | 애플리케이션 플랫폼이 식별 유형과 일치하지 않음 |
e320 | 잘못된 identity_type |
e321 | LAT 사용자가 API를 통해 지원되지 않음 |
e322 | 잘못된 subject_request_type |
e323 | 잘못된 subject_identities 형식 |
e324 | 잘못된 subject_identities 길이 |
e325 | 잘못된 subject_identities 값 |
e411 | AppID가 올바르지 않거나 사용자 계정에 속하지 않음 |
e412 | 삭제 요청을 취소할 수 있는 권한이 없음 |
e413 | 요청을 볼 수 있는 권한이 없음 |
e511 | 내부 문제, 60분 기다렸다가 다시 시도하십시오. 문제가 지속되면 앱스플라이어 지원 부서에 문의하십시오. support@AppsFlyer.com |
제한 사항
- 속도 제한: 계정 수준에서 2분마다 80개의 GDPR 요청.