SDK ์‚ฝ์ž…

1. ํ•„์ˆ˜ ์„ค์ •

SDK ์„ค์น˜

Cocoapod ํ™˜๊ฒฝ์—์„œ SDK ๋‹ค์šด๋กœ๋“œ ๋ฐฉ๋ฒ•

XCode ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์ค‘ Podfile ํŒŒ์ผ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด SDK๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค

pod 'RW'

๊ธฐ์กด์— SDK๋ฅผ ํ•œ๋ฒˆ ์„ค์น˜ํ•œ ๊ฒฝ์šฐ์—๋Š” ์„ค์น˜ํ• SDK ๋ฒ„์ „์„ ํ‘œ์‹œํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์น˜ํ•  SDK๋ฒ„์ „์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œ์‹œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

pod 'RW', '~> 1.1.62'

Podfile ์— ํ•ด๋‹น๋ผ์ธ์„ ์ถ”๊ฐ€ํ•œ ํ›„ Terminal ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜์—ฌ ๋‹ค์Œ์˜ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค

pod install

SDK ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ์˜ ๊ฒฝ์šฐ ๋‹ค์Œ์˜ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

pod update

์ •์ƒ์ ์œผ๋กœ ์„ค์น˜๊ฐ€ ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํด๋” ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Swift Package Manager๋ฅผ ํ†ตํ•œ SDK ๋‹ค์šด๋กœ๋“œ ๋ฐฉ๋ฒ•

Xcode File ๋ฉ”๋‰ด์—์„œ Add Packages... ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

RW-iOS-SPM ๋˜๋Š” https://github.com/WisetrackerTechteam/RW-iOS-SPM ์ฃผ์†Œ๋กœ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

์ตœ์‹  ๋ฒ„์ „์˜ ํŒจํ‚ค์ง€๋กœ ์„ ํƒ ํ›„, Add Package ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

์™„๋ฃŒ๋˜๋ฉด ์„ค์น˜๋œ ํŒจํ‚ค์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TARGETS โ†’ Build Phases โ†’ Copy Bundle Resources ์— dop-native-sdk-inf.js ํŒŒ์ผ์„ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋žํ•˜์—ฌ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

SDK ์„ค์น˜ - Cocoapod, Swift Package Manger๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ

SDK ํŒŒ์ผ์„ https://github.com/WisetrackerTechteam/RW-iOS-SDK ์—์„œ ๋‹ค์šด๋กœ๋“œ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์šด๋œ ํŒŒ์ผ์„ ์••์ถ• ํ•ด์ œํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ์ด ํ™•์ธ ๊ฐ€๋Šฅํ•˜๊ณ  ์ด์ค‘ ์•„๋ž˜์— ์„ ํƒ๋œ 3๊ฐœ์˜ ํŒŒ์ผ์„ ๋ถ„์„ ๋Œ€์ƒ ์•ฑ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ์„ ํƒํ›„ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ, Add Files to ๋ฉ”๋‰ด๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

์•ž์—์„œ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ณ , ์••์ถ• ํ•ด์ œํ•œ ํด๋”์— ๋“ค์–ด๊ฐ€์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ถ”๊ฐ€ ๋Œ€์ƒ ํŒŒ์ผ์„ ์„ ํƒํ•˜๊ณ , ํ™”๋ฉด ์•„๋ž˜์ชฝ ์„ค์ •์€ ์กด์žฌํ•˜๋Š” ๋ชจ๋“  target์— ํฌํ•จ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ›„ ์ถ”๊ฐ€ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

BuildSetting ์— ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

xcode ๊ฐ€ 12.3 ์ดํ›„ ๋ฒ„์ „์ด๊ณ  ๋นŒ๋“œ ๊ณผ์ •์—์„œ ์•„๋ž˜์™€ ์œ ์‚ฌํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋ฉฐ,

์œ„์˜ ๊ฒฝ์šฐ์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •์„ ํ•˜๊ณ , ๋นŒ๋“œ๋ฅผ ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ, SDK ๊ฐ€ Dependencies ๋กœ ์‚ฌ์šฉํ•˜๋Š” Couchbase-Lite framework ๋ฅผ ์•„๋ž˜์˜ ์ฃผ์†Œ์—์„œ ๋‹ค์šด๋กœ๋“œ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์œ„์™€ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋Œ€์ƒ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ค๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ํŒŒ์ผ์€ ๋‹ค์šด๋กœ๋“œ ํŽธ์˜๋ฅผ ์œ„ํ•ด์„œ zip ํŒŒ์ผ๋กœ ์••์ถ•ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋‹ค์šด๋กœ๋“œ ๋ฐ›์€ ํŒŒ์ผ์„ ์••์ถ• ํ•ด์ œํ•˜์‹œ๊ณ , CouchbaseLite.xcframework ํด๋”๋ฅผ ํ”„๋กœ์ ํŠธ์— framework ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. https://wisetracker-public.s3.ap-northeast-2.amazonaws.com/CouchbaseLite.xcframework.zip

dotAuthorizationKey ๋“ฑ๋ก

info.plist ํŒŒ์ผ์„ Open As Source Code ๋ฐฉ์‹์œผ๋กœ ์˜คํ”ˆํ•œ ํ›„, ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<key>dotAuthorizationKey</key>
<dict>
    <key>serviceNumber</key>
    <string>xxxxx</string>
    <key>expireDate</key>
    <string>14</string>
    <key>isDebug</key>
    <string>true</string>
    <key>isInstallRetention</key>
    <string>true</string>
    <key>isFingerPrint</key>
    <string>true</string>
    <key>accessToken</key>
    <string></string>
    <key>useMode</key>
    <string>2</string>
</dict>

์ถ”๊ฐ€ํ•œ ์ฝ”๋“œ ์ค‘ serviceNumber ์˜ value๋ฅผ ์˜ฌ๋ฐ”๋ฅธ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™€์ด์ฆˆํŠธ๋ž˜์ปค ๋Œ€์‹œ๋ณด๋“œ์— ๋กœ๊ทธ์ธํ•˜์—ฌ ์„ค์ • > ์„œ๋น„์Šค์„ค์ • ๋ฉ”๋‰ด์—์„œ '์„œ๋น„์Šค๋ฒˆํ˜ธ' ํ•ญ๋ชฉ์— ๊ธฐ์žฌ๋œ ์ˆซ์ž๋ฅผ ํ™•์ธ ํ›„ ๋ณต์‚ฌํ•˜์—ฌ serviceNumber ๊ฐ’์„ ๋ณ€๊ฒฝ ํ•ด ์ฃผ์„ธ์š”.

์„œ๋น„์Šค๋ฒˆํ˜ธ ํ™•์ธ

HTTP ํ†ต์‹  ํ—ˆ์šฉ

httpํ†ต์‹ ์„ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด NSAppTransportSecurity ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ด์ „๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ info.plist ํŒŒ์ผ์„ Open As Source Code ๋ฐฉ์‹์œผ๋กœ ์˜คํ”ˆํ•œ ํ›„, ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

์ดˆ๊ธฐํ™”

  • ์ดˆ๊ธฐํ™” ๋ฐฉ๋ฒ•์€ SceneDelegate ๊ฐ€ ์„ค์ •๋œ ๊ฒฝ์šฐ์™€ ์„ค์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

  • SceneDelegate๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด AppDelegate์—์„œ ์ดˆ๊ธฐํ™”์ž‘์—…์„ ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š๊ณ  SceneDelegate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด SceneDelegate์—์„œ ์ด ์ž‘์—…์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1. iOS13 ๋ฏธ๋งŒ (SceneDelegate ์—†์Œ)

AppDelegate์˜ didFinishLaunchingWithOptions ํ•จ์ˆ˜์— SDK๋ฅผ Initializationํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. SDK๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ดˆ๊ธฐํ™” ๋˜์—ˆ์„ ๋•Œ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋ณธ ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ์•ฑ ์‹คํ–‰ ๋ฐ ๋ฐฉ๋ฌธ์ˆ˜, ์ผ/์ฃผ/์›”์ˆœ์ˆ˜๋ฐฉ๋ฌธ์ˆ˜ ๋“ฑ ๋ฐฉ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ์ง€ํ‘œ

  • ํ†ต์‹ ์‚ฌ, ๋‹จ๋ง๊ธฐ, ๊ตญ๊ฐ€ ๋“ฑ ๋ฐฉ๋ฌธ์ž์˜ ๋‹จ๋ง๊ธฐ ํ™˜๊ฒฝ์œผ๋กœ ๋ถ€ํ„ฐ ์ถ”์ถœ๋  ์ˆ˜ ์žˆ๋Š” ์ง€ํ‘œ

import DOT
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  // S: Wisetracker SDK init
  DOT.initialization(launchOptions, application: application)
  #if DEBUG
    DOT.checkDebugMode(true)
  #else
    DOT.checkDebugMode(false)
  #endif
  // E: Wisetracker SDK init
}

DOT๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ณณ์—์„œ๋Š” import DOT์„ ํ†ตํ•ด import๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ดํ•˜ ์ ์šฉ ์˜ˆ์‹œ์—์„œ๋Š” importํ•˜๋Š” ๋ถ€๋ถ„์ด ์ƒ๋žต๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

2. iOS13 ์ด์ƒ (SceneDelegate ์‚ฌ์šฉ)

๐Ÿ‘‰ iOS13 ์ด์ƒ์ด์–ด๋„ SceneDelegate๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์–ด์š”, ์ด ๋•Œ์—๋Š” ์œ„์˜ SceneDelegate๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

SceneDelegate์˜ sceneDidBecomeActiveํ•จ์ˆ˜์— SDK๋ฅผ Initializationํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. SDK๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ดˆ๊ธฐํ™” ๋˜์—ˆ์„ ๋•Œ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋ณธ ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ์•ฑ ์‹คํ–‰ ๋ฐ ๋ฐฉ๋ฌธ์ˆ˜, ์ผ/์ฃผ/์›”์ˆœ์ˆ˜๋ฐฉ๋ฌธ์ˆ˜ ๋“ฑ ๋ฐฉ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ์ง€ํ‘œ

  • ํ†ต์‹ ์‚ฌ, ๋‹จ๋ง๊ธฐ, ๊ตญ๊ฐ€ ๋“ฑ ๋ฐฉ๋ฌธ์ž์˜ ๋‹จ๋ง๊ธฐ ํ™˜๊ฒฝ์œผ๋กœ ๋ถ€ํ„ฐ ์ถ”์ถœ๋  ์ˆ˜ ์žˆ๋Š” ์ง€ํ‘œ

import DOT

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
...
  func sceneDidBecomeActive(_ scene: UIScene) {
    // S: Wisetracker SDK init
    DOT.initialization(nil, application: UIApplication.shared)
    #if DEBUG
      DOT.checkDebugMode(true)
    #else
      DOT.checkDebugMode(false)
    #endif
    // E: Wisetracker SDK init
  }
...
}

์–ดํŠธ๋ฆฌ๋ทฐ์…˜ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ

[DOT getAttributedInfo] ํ˜ธ์ถœ์„ ํ†ตํ•ด ์™€์ด์ฆˆํŠธ๋ž˜์ปค ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์ƒ์„ฑํ•œ ์–ดํŠธ๋ฆฌ๋ทฐ์…˜๋งํฌ๋ฅผ ํ†ตํ•ด ์•ฑ์„ ์„ค์น˜ํ•œ ์œ ์ €(non-organic)์˜ attribute ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… ํ•„์ˆ˜ ์ฒดํฌ ์‚ฌํ•ญ

1

iOS SDK ์ตœ์‹ ๋ฒ„์ „์ด ์ ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

2

SDK ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ DOT.initializationํ˜ธ์ถœํ•œ ์ดํ›„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

#import <DOT/DOT.h>

@implementation SceneDelegate
...
- (void)sceneDidBecomeActive:(UIScene *)scene {
  // S: Wisetracker SDK init
  [DOT initialization:nil application:[UIApplication sharedApplication]];
  #ifdef DEBUG
    [DOT checkDebugMode:true]
  #else
    [DOT checkDebugMode:false]
  #endif
  // E: Wisetracker SDK init
  
  [DOT getAttributedInfo:^(NSDictionary *result) {
    // info๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—… ์ˆ˜ํ–‰
    NSLog(@"current attribution data on AppDelegate : %@ ", result);
  }];
}
...
@end

result ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํ˜•ํƒœ๋Š” ์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ  ํ•ด์ฃผ์„ธ์š”.

(result ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด Organic ์œผ๋กœ ์‹๋ณ„๋œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค.)

โ‘  ์•ฑ์„ค์น˜(์˜ˆ์‹œ)

{
  install_media="P1540365166967",      >> ๊ด‘๊ณ ์ฑ„๋„    
  install_mediaNm="WISE_TEST1",        >> ๊ด‘๊ณ ์ฑ„๋„๋ช… 
  install_campaign="C1710215861051",   >> ๊ด‘๊ณ ์บ ํŽ˜์ธ  
  install_campaignNm="WISETRACKER",    >> ๊ด‘๊ณ ์บ ํŽ˜์ธ๋ช…
  install_medium="",                   >> ๊ด‘๊ณ ํƒ€์ž…
  install_keyword=""                   >> ๊ด‘๊ณ ํ‚ค์›Œ๋“œ   
}

โ‘ก ์•ฑ์‹คํ–‰(์˜ˆ์‹œ)

{
  open_media="P1540365166967",
  open_mediaNm="WISE_TEST1",
  open_campaign="C1710215861051",
  open_campaignNm="WISETRACKER",
  open_medium="",
  open_keyword=""
}

Hybrid App์„ ์œ„ํ•œ ์„ค์ •

Hybrid ์•ฑ์˜ ๊ฒฝ์šฐ ์•ฑ ๋‚ด์—์„œ WebView ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ์ปจํ…์ธ ๋ฅผ ์„œ๋น„์Šค ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์ด Webview ์— ์˜ํ•ด์„œ ๋ณด์—ฌ์ง€๋Š” ์›น ์ปจํ…์ธ ์˜ ๊ฒฝ์šฐ์—๋Š” ์œ„์—์„œ ์„ค๋ช…๋œ Native ํ™”๋ฉด๊ณผ๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ณ„๋„์˜ ๋ถ„์„ ์ฝ”๋“œ ์ ์šฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ถ„์„ ๋Œ€์ƒ ์•ฑ์ด ๋งŒ์•ฝ Hybrid ์•ฑ์ธ ๊ฒฝ์šฐ์—๋Š” ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์›น ์ปจํ…์ธ ๋„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ ์šฉ์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์•ฑ๋‚ด์—์„œ ์‚ฌ์šฉํ•  WKWebView์˜ Delegate ํ•จ์ˆ˜์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋ถ„์„์ฝ”๋“œ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

extension WebViewController: WKUIDelegate, WKNavigationDelegate {
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    DOT.injectSdk(toHtmlDocument: webView, withStartPage: true );
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
    DOT.injectSdk(toHtmlDocument: webView,  withStartPage: false);
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    DOT.injectJavascript(withDomSearch: webView, isOnPageFinished: true)
}

  func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
       ...
      if let url = navigationAction.request.url{
         let absoluteString = url.absoluteString
          if (absoluteString.hasPrefix("jscall-dot")) {
             let request: URLRequest? = navigationAction.request
             DOT.setWkWebView(webView, reqeust: request)            
              decisionHandler(.cancel)
             return;
              }          
               ...
         }     
           ...
}

๋ชจ๋ฐ”์ผ์•ฑ๋‚ด ์›น๋ทฐ์™€ PC ํ˜น์€ ๋ชจ๋ฐ”์ผ์›น๋ทฐ๋กœ ๋™์‹œ์— ์‚ฌ์šฉํ•˜๋Š” ํ™”๋ฉด์ธ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์€ ์›นํ‚ท๋ทฐ๋ฅผ ํฌํ•จํ•œ viewController์˜ viewWillApeear์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ ์šฉํ•ด์ฃผ์„ธ์š”.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    webView.evaluateJavaScript("navigator.userAgent") { (userAgent, error) in
         if let ua = userAgent {
            self.webView.customUserAgent = ua as! String + " RW2SDK"
         }
     }
}

์ด๋ฒคํŠธ ์„ค์ •

โœ…ํ™”๋ฉด์ „ํ™˜ ๋˜๋Š” ์ด๋ฒคํŠธ ๋ถ„์„์„ ์œ„ํ•œ ์ ์šฉ ๋ฐฉ๋ฒ•์€ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์ • ๋ฐ ์ดˆ๊ธฐํ™” ์ดํ›„์— ์•„๋ž˜ ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๊ฑฐ๋‚˜, ์ขŒ์ธก IN-APP EVENT ๋ฉ”๋‰ด๋ฅผ ํ†ตํ•ด ๊ฐ€์ด๋“œ๋ฅผ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ‘‰ํŽ˜์ด์ง€ ๋ถ„์„ ๊ฐ€์ด๋“œ๋กœ ์ด๋™ํ•˜๊ธฐ

๐Ÿ‘‰์ธ์•ฑ ์ด๋ฒคํŠธ ์„ค์ •์œผ๋กœ ์ด๋™ํ•˜๊ธฐ

2. ๊ณ ๊ธ‰ ์„ค์ •

๊ณ ๊ธ‰ ์„ค์ •์ด๋ž€ ๋ฐ˜๋“œ์‹œ ์ ์šฉํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ ์™€์ด์ฆˆํŠธ๋ž˜์ปค์˜ ํ™•์žฅ๋œ ๋ถ„์„๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ์„ค์ •์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ ์„ ํƒ์ ์œผ๋กœ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์œ ๋‹ˆ๋ฒ„์…œ ๋งํฌ ์„ค์ • ๊ฐ€์ด๋“œ๋Š” ๋ณ„๋„์˜ ๋ฌธ์„œ์— ์ •๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

Universal Link ์„ค์ •

continueUserActivity ๋ถ€๋ถ„์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ ์šฉ์ด ๋˜๋ฉด ์œ ๋‹ˆ๋ฒ„์…œ ๋งํฌ๋ฅผ ํ†ตํ•œ ๊ด‘๊ณ ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•ด์ฃผ์„ธ์š”
    if let uniLink = userActivity.webpageURL?.absoluteString {
        DOT.setDeepLink(uniLink)
        let landingUri :String = DOT.parseAttributionLink(toGetDeeplinkUrl: uniLink)
         // ๋ฆฌํ„ด๋ฐ›์€ landingUri๊ฐ’(DeepLink Sheme)์œผ๋กœ ํ™”๋ฉด ์ง„์ž… ๋กœ์ง ๊ตฌํ˜„(๊ธฐ์กด open url์—์„œ ์‚ฌ์šฉํ•˜๋˜ ํ™”๋ฉด ์ด๋™ ๋กœ์ง๊ณผ ๋™์ผํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋จ)
    }
    //
    return false;
 }
  • ๋”ฅ๋งํฌ๊ฐ€ ์„ค์ •๋œ url ์„ ํ†ตํ•ด์„œ ์˜คํ”ˆ๋œ ์ด๋ฒคํŠธ๋ฅผ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. ๋ถ„์„์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•ฑ์— custom url scheme ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

โœ”๏ธ์™€์ด์ฆˆํŠธ๋ž˜์ปค ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์ƒ์„ฑํ•œ ์–ดํŠธ๋ฆฌ๋ทฐ์…˜๋งํฌ๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ ๋ฐ ๊ด‘๊ณ ์ง‘ํ–‰์„ ์ง„ํ–‰ํ•˜๋ฉฐ, ๋”ฅ๋งํฌ ํด๋ฆญ ์‹œ ์™€์ด์ฆˆํŠธ๋ž˜์ปค ์„œ๋ฒ„๊ฐ€ ์•ฑ์˜ ์„ค์น˜ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜์—ฌ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ์˜ "https://xxxx.page.link" ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น URL์ด ๊ฐ€๋ฅดํ‚ค๋Š” ์›น์œผ๋กœ ์ด๋™ํ•จ์œผ๋กœ์จ ์™€์ด์ฆˆํŠธ๋ž˜์ปค๊ฐ€ ์ˆ˜์ง‘ํ•˜์—ฌ์•ผ ํ•˜๋Š” ๊ด‘๊ณ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’์ด ์œ ์‹ค๋  ์ˆ˜ ์žˆ์–ด, ์•ฑ์œผ๋กœ ๋ฐ”๋กœ ์ด๋™ ๊ฐ€๋Šฅํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ์˜ Unique ํ•œ ์ปค์Šคํ…€์Šคํ‚ค๋งˆ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ์œ ๋‹ˆ๋ฒ„์…œ๋งํฌ๊ฐ€ ์กด์žฌ ํ•œ๋‹ค๋ฉด ์™€์ด์ฆˆํŠธ๋ž˜์ปค์—์„œ ์‚ฌ์šฉํ•  ๋”ฅ๋งํฌ ์ง„์ž… ์Šคํ‚ค๋งˆ ์„ค์ •์„ '์ถ”๊ฐ€' ํ•ด ์ฃผ์„ธ์š”. (๋”ฅ๋งํฌ์Šคํ‚ค๋งˆ ์„ค์ • ์ถ”๊ฐ€์‹œ ๋‹ค๋ฅธ ๋งํฌ์— ์–ด๋– ํ•œ ์˜ํ–ฅ๋„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

์œ„์™€ ๊ฐ™์ด ์„ค์ •์„ ๋งˆ์น˜์‹œ๊ฒŒ ๋˜์‹œ๋ฉด ์˜ˆ๋ฅผ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™ ํ˜•ํƒœ์˜ ์ปค์Šคํ…€ ์Šคํ‚ค๋งˆ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

wisetracker://wisetracker.co.kr

์—ฌ๊ธฐ์„œ wisetracker:// ๋ถ€๋ถ„์ดScheme(ํ˜น์€ ํ”„๋กœํ† ์ฝœ) ์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์•ฑ์— ์ด Scheme๋ฅผ ์“ธ ๊ฒƒ์ด๋ผ๊ณ  ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ํ•ด๋‹น Scheme๋งŒ ์„ค์ •์„ ํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค.

์ด์–ด์„œ wisetracker.co.kr ๋ถ€๋ถ„์€ ํŠน์ • ํŽ˜์ด์ง€์— ๋„๋‹ฌํ•˜๋„๋ก ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ host(ํ˜น์€ path or ๋„๋ฉ”์ธ) ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  wisetracker://wisetracker.co.kr?product=1 ์ด๋Ÿฌํ•œ ํ˜•ํƒœ๋กœ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ๋Š” ํŠน์ • ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ธฐ ์œ„ํ•œ parameter ๊ฐ’์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ ํ•ด๋‹น ๋ถ€๋ถ„์€ ์™€์ด์ฆˆํŠธ๋ž˜์ปค์˜ SDK๊ฐ€ ์•„๋‹Œ ๊ณ ๊ฐ์‚ฌ์ธก์—์„œ ์ง์ ‘ ์„ค์ •ํ•ด์ฃผ์…”์•ผ ํ•˜๋Š” ๊ฐ’์ด๋ฉฐ, ํŠน์ • ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด parameter ๊ฐ’์€ ๊ผญ ์„ค์ •ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

๋”ฅ๋งํฌ ๋ถ„์„

  • ์•ฑ์ด ์„ค์น˜๋œ ์ดํ›„ DeepLink๋ฅผ ํ†ตํ•ด์„œ ์•ฑ์ด ์‹คํ–‰๋˜๋Š” ๊ฒฝ๋กœ ๋ถ„์„์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด setDeepLink ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
	DOT.setDeepLink(url.absoluteString)
	return true
}

์™€์ด์ฆˆํŠธ๋ž˜์ปค SDK๋ฅผ ์ ์šฉํ•˜๊ณ , ๊ด‘๊ณ  ๋ถ„์„์„ ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ, ์™€์ด์ฆˆํŠธ๋ž˜์ปค ์‹œ์Šคํ…œ์—์„œ ๋ฐœ๊ธ‰๋œ ๊ด‘๊ณ  ๋ถ„์„ ๋งํฌ์— ์˜ํ•ด์„œ ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š” ๋”ฅ๋งํฌ URL์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ด‘๊ณ  ๋ถ„์„ ๋ชฉ์ ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ ์›น์•ฑ์˜ ๊ฒฝ์šฐ url ์ด๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น๋ทฐ์— ๋กœ๋”ฉ๋˜์–ด์งˆ ์›นํŽ˜์ด์ง€ url์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ, ์ด์™€ ๊ด€๋ จํ•˜์—ฌ ์•„๋ž˜์˜ ์ผ€์ด์Šค์—๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

// ๊ธฐ์กด์˜ deeplink ์— ๊ด‘๊ณ  ๋ถ„์„ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์ถ”๊ฐ€๋œ ์˜ˆ์‹œ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
YOUR_SCHEMA://YOUR_HOST?url={YOUR_WEB_PAGE_URL}&trackId=M00200881641977334670
&w_start=h&_wtno=102&_wts=P1641977288745
... ์ค‘๊ฐ„ ์ƒ๋žต ...
&w_end=h
๋”ฅ๋งํฌ ์„ค์ • ํ›„ ํ…Œ์ŠคํŠธ์‹œ ๊ฐ€์ด๋“œ๋ถ์„ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

Deffered Deep Link (์ง€์—ฐ๋œ ๋”ฅ๋งํฌ) ์ ์šฉ

  1. ์ง€์—ฐ๋œ ๋”ฅ๋งํฌ ๊ธฐ๋Šฅ์€ Growth ๋ ˆ๋ฒจ ์ด์ƒ์˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

  2. ์ง€์—ฐ๋œ ๋”ฅ๋งํฌ ๊ธฐ๋Šฅ ์ œ๊ณต SDK ๋ฒ„์ „ - Android SDK: Base Modeul - 1.0.81 ์ด์ƒ / New Dot Module - 1.0.51 ์ด์ƒ - iOS SDK: RW 1.1.52 ์ด์ƒ

๊ธฐ์กด์˜ [DOT initialization] SDK ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ ๋Œ€์‹  ์•„๋ž˜์˜ [DOT initializationForDeferredCallback] ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ์ˆ˜์‹ ๋œ ์ง€์—ฐ๋œ ๋”ฅ๋งํฌ์˜ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.


// your code...

[DOT initializationForDeferredCallback:launchOptions application:application callback:^{
    // deferred deeplink  ์ •๋ณด๋Š” [DOT getDeferredUrl]๋กœ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ,
    // ์•ฑ์—์„œ๋Š” ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•   ์ˆ˜ ์žˆ์Œ. 
    // 1. callback ์ด ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์— ์ฆ‰์‹œ __deferredUrl ํ™”๋ฉด์œผ๋กœ ์ด๋™ ์ฒ˜๋ฆฌ. __deferredUrl ๊ฐ’์ด nil ์ด๋ฉด ๋ฉ”์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ ์ฒ˜๋ฆฌ. 
    // 2. __deferredUrl ๋ณ€์ˆ˜๊ฐ’์„ ์–ด๋”˜๊ฐ€์— ์ €์žฅํ•˜๊ณ , ํšŒ์›๊ฐ€์ž… ์ดํ›„, ๋กœ๊ทธ์ธ์ด ์™„๋ฃŒ๋œ ์ดํ›„๋“ฑ๊ณผ ๊ฐ™์ด ํ•„์š”ํ•œ ์‹œ์ ์— ์ €์žฅ๋œ ๊ฐ’์„ ๊บผ๋‚ด์„œ ์ด๋™ ์ฒ˜๋ฆฌ. 
    // 3. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ Deferred deeplink ์ •๋ณด๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š”, __deferredUrl ๊ฐ’์ด ๋„(NULL) ์ด ๋  ์ˆ˜ ์žˆ์Œ์„ ๊ณ ๋ คํ•˜์—ฌ ์‚ฌ์šฉ. 
    NSString* __deferredUrl = [DOT getDeferredUrl];
    NSLog(@"Deferred callback executed %@", __deferredUrl);
}];

// your code...

์œ„์™€ ๊ฐ™์ด ์ง€์—ฐ๋œ ๋”ฅ๋งํฌ์— ๋Œ€ํ•œ ๋Œ€์‘ ์ฝ”๋“œ๊ฐ€ ์ ์šฉ๋œ ์ดํ›„์— ์™€์ด์ฆˆํŠธ๋ž˜์ปค ๋Œ€์‰ฌ๋ณด๋“œ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์–ดํŠธ๋ฆฌ๋ทฐ์…˜ ๋งํฌ๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ง€์—ฐ๋œ ๋”ฅ๋งํฌ(๋””ํผ๋“œ ๋”ฅ๋งํฌ)๊ฐ€ ์‚ฌ์šฉ๋œ ์–ดํŠธ๋ฆฌ๋ทฐ์…˜ ๋งํฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งŒ์•ฝ ์•ฑ์ด ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์•˜๋˜ ๊ฒฝ์šฐ๋ผ๋ฉด, ๋จผ์ € ์•ฑ ์„ค์น˜๋ฅผ ์œ„ํ•ด ๋งˆ์ผ“(๊ตฌ๊ธ€์Šคํ† ์–ด, ์•ฑ์Šคํ† ์–ด)์œผ๋กœ ์ด๋™๋˜๊ณ , ์•ฑ ์„ค์น˜ ์ดํ›„์— ์•ฑ์„ ์‹คํ–‰์‹œํ‚ค๊ฒŒ ๋˜๋ฉด NSString* __deferredUrl ๋ณ€์ˆ˜์— ์„ค์ •ํ•œ ์•ฑ ์‹คํ–‰ ๋งํฌ๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ: wisetester://mainscreen)

๋”ฐ๋ผ์„œ ๋“ค์–ด๊ฐ€ ์žˆ๋Š” (๋””ํผ๋“œ) ๋”ฅ๋งํฌ ๊ฐ’์— ๋”ฐ๋ผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ์ดํ›„ ์•ก์…˜์— ๋Œ€ํ•ด ๋Œ€์‘๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐœ๋ฐœํ•ด ์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Facebook ๊ด‘๊ณ  ์„ฑ๊ณผ ์ธก์ •

Facebook ์•ฑ์—์„œ ์œ ์ž…๋˜๋Š” ์„ค์น˜์ˆ˜๋ฅผ ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Facebook์—์„œ ์ œ๊ณตํ•˜๋Š” SDK๊ฐ€ ๋ถ„์„ ๋Œ€์ƒ ์•ฑ์— ์„ค์น˜๊ฐ€ ์„ ํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋น„์ฆˆ๋‹ˆ์Šค ์ธ์ฆ

Facebook Developer ์‚ฌ์ดํŠธ์˜ ์•ฑ์„ค์ •-๊ธฐ๋ณธ์„ค์ •์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ์ธ์ฆ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ ํ•ด ์ฃผ์„ธ์š”. ๋น„์ฆˆ๋‹ˆ์Šค ์ธ์ฆ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ, ๋ฆฌํผ๋Ÿฌ ์ •๋ณด๊ฐ€ ์ˆ˜์‹ ๋˜์ง€ ์•Š์•„, facebook ๊ด‘๊ณ  ์„ฑ๊ณผ์— ๋Œ€ํ•œ ์ธก์ •์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

FBSDK ๋‹ค์šด๋กœ๋“œ ๋ฐฉ๋ฒ•

1) XCode ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์ค‘ Podfile ํŒŒ์ผ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด SDK๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค

pod โ€˜FBSDKCoreKitโ€™, โ€˜11.2.1โ€™

2) Podfile ์— dependency ๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค์—๋Š” Terminal ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜์—ฌ ๋‹ค์Œ์˜ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค

cmd> pod install

FBSDK ์„ค์น˜ ๋ฐฉ๋ฒ•

1) info.plist ํŒŒ์ผ์„ source๋กœ ๋ณด๊ธฐ ๋กœ ์˜คํ”ˆํ•ฉ๋‹ˆ๋‹ค

2) ์ด๋ฆ„ ์†์„ฑ ์•„๋ž˜์— ํฌํ•จ๋œ ๋‚ด์šฉ์ค‘ [APP_ID] , [APP_NAME] , [CLIENT_TOKEN] ๋ถ€๋ถ„์„ Facebook Developer Site ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฐ’์œผ๋กœ ์น˜ํ™˜ํ›„ info.plist ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>fb</string>
        </array>
    </dict>
</array>
<key>FacebookAppID</key>
<string>[APP_ID]</string>
<key>FacebookDisplayName</key>
<string>[APP_NAME]</string>
<key>FacebookClientToken</key>
<string>[CLIENT_TOKEN]</string>
<key>FacebookAdvertiserIDCollectionEnabled</key>
<true/>

FBSDK ๋กœ๋ถ€ํ„ฐ Install Referrer๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ , SDK์— ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•

์‚ฌ์šฉ์ž๊ฐ€ Facebook์— ๋…ธ์ถœ๋œ ๊ด‘๊ณ ๋ฅผ ํด๋ฆญํ•˜๊ณ  ์•ฑ์„ ์„ค์น˜ํ•œ ๊ฒฝ์šฐ ์„ค์น˜๋œ ์•ฑ์—์„œ๋Š” FBSDK๋ฅผ ํ†ตํ•ด์„œ AppLinkData๋ฅผ ์ˆ˜์‹ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์ฝ”๋“œ์—์„œ FBSDK๋กœ๋ถ€ํ„ฐ AppLinkData๋ฅผ ์ˆ˜์‹  ๋ฐ›๊ณ , ์ˆ˜์‹  ๋ฐ›์€ AppLinkData ๋ฅผ SDK๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” appDelegate์˜ didFinishLaunchingWithOptions ํ•จ์ˆ˜์— ์ ์šฉํ•˜์„ธ์š”. SDK ์ดˆ๊ธฐํ™” ์ด ํ›„์— DOT.setFacebookreferrerData() ํ˜ธ์ถœ์„ ํ†ตํ•ด SDK์— ๋ฆฌํผ๋Ÿฌ url ์ด ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” Facebook ์œผ๋กœ๋ถ€ํ„ฐ Install Referrer๋ฅผ ์ˆ˜์‹ ๋ฐ›๊ธฐ ์œ„ํ•ด, ATT ๋™์˜ ํ™•์ธ > ๋™์˜ ์—ฌ๋ถ€์— ๋”ฐ๋ผ SDK์— Facebook ๋ฆฌํผ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ ์ž…๋‹ˆ๋‹ค.

import AppTrackingTransparency
import AdSupport
import FBSDKCoreKit
import DOT

func requestTrackingPermission() {
    
    // iOS 14 ์ด์ƒ์ธ์ง€ ์ฒดํฌ
    if #available(iOS 14, *) {
      ATTrackingManager.requestTrackingAuthorization { (AuthorizationStatus) in
        switch AuthorizationStatus {
            // ATT ๋™์˜
            case .authorized:
              Settings.setAdvertiserTrackingEnabled(true)
              DispatchQueue.main.async(execute: { [] in
                AppLinkUtility.fetchDeferredAppLink({ url, error in
                  if error != nil {
                    if let anError = error {
                      print("๐Ÿ˜€ Received error while fetching deferred app link: \(anError)")
                    }
                  }
                  if let unwrappedUrl = url {
                    // Facebook Deferred link ์ˆ˜์‹  & SDK ์ „๋‹ฌ.
                     print("๐Ÿ˜€ fetchDeferredAppLink: \(url.absoluteString)")
                      DOT.setFacebookreferrerData(url)
                  }
                })
              })
              // SDK์— IDFA ์„ค์ •
              DOT.setIDFA(ASIdentifierManager.shared().advertisingIdentifier.uuidString)
            
            //  ATT ๊ฑฐ๋ถ€ ๋ฐ ๊ธฐํƒ€
            @unknown default:
              DOT.denyATT();
        }
      }
    }
    // iOS 14 ์ดํ•˜
    else {
      DOT.setATTAuthorizationStatus(3)
      AppLinkUtility.fetchDeferredAppLink({ url, error in
        if error != nil {
          if let anError = error {
            print("๐Ÿ˜€ Received error while fetching deferred app link: \(anError)")
          }
        }
        if let unwrappedUrl = url {
          // Facebook Deferred link ์ˆ˜์‹  & SDK ์ „๋‹ฌ.
            DOT.setFacebookreferrerData(unwrappedUrl)
        }
      });
    }
}

Facebook SDK์™€ ๊ด€๋ จํ•˜์—ฌ ๋ณด๋‹ค ์ž์„ธํ•œ ์„ค์น˜ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์˜ ๋งํฌ์—์„œ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

FBSDK iOS ์ ์šฉ๋ฐฉ๋ฒ• ์ž์„ธํžˆ ๋ณด๊ธฐ

์•ฑ ์„ค์น˜ํ˜• ๊ด‘๊ณ  ํ…Œ์ŠคํŠธ์‹œ ํ™•์ธ ํŒ์—…

4. iOS 14 ๊ฐœ์ธ์ •๋ณด๋ฐฉ์นจ ๋ณ€๊ฒฝ ๊ด€๋ จ ๊ฐ€์ด๋“œ

  • iOS 14๋ถ€ํ„ฐ IDFA๋ฅผ ํš๋“ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์‚ฌ์šฉ์ž์˜ ๋™์˜๋ฅผ ์–ป์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3.1 info.plistํŒŒ์ผ์— NSUserTrackingUsageDescription ์„ค์ • ์ถ”๊ฐ€

<key>NSUserTrackingUsageDescription</key>
<string>Your data will be used to deliver personalized ads to you.</string>

3.2 App Tracking Transparency ๋™์˜ System Alert ๋…ธ์ถœ & API ํ˜ธ์ถœ

  • IDFA ํš๋“์„ ์œ„ํ•ด ์•ฑ ์ถ”์  ํˆฌ๋ช…์„ฑ ๋™์˜ ์š”์ฒญ System Alert(๋Œ€ํ™” ์ƒ์ž)์„ ๋„์›Œ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋™์˜ ์š”์ฒญ System Alert(๋Œ€ํ™” ์ƒ์ž) ํ™”๋ฉด์— ๋„์šฐ๋ ค๋ฉด requestTrackingAuthorizationWithCompletionHandler:๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. completionHandler์—์„œ ๋™์˜ ์‹œ SDK API๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์œ„์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

import AppTrackingTransparency
import AdSupport
if #available(iOS 14, *) {
	ATTrackingManager.requestTrackingAuthorization { (AuthorizationStatus) in
		if(AuthorizationStatus == .authorized) {
			DOT.setIDFA(ASIdentifierManager.shared().advertisingIdentifier.uuidString)
		}
	}
} else {
	DOT.setATTAuthorizationStatus(3)
}

Last updated

Was this helpful?