> For the complete documentation index, see [llms.txt](https://document.wisetracker.co.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://document.wisetracker.co.kr/v2-developer/in-app-event/configuration/page.md).

# 페이지 분석

{% hint style="info" %}
Wisetracker SDK는 <mark style="color:red;">**DOT.onStartPage()**</mark> 함수를 만나면 PAGES 유형의 페이지뷰 이벤트 (DOT.logScreen)를 수집하고 있습니다.&#x20;

<mark style="color:red;">**A페이지의 onStartPage()**</mark>**&#x20;->** <mark style="color:blue;">**A페이지의**</mark> <mark style="color:blue;">**DOT.logScreen**</mark>**&#x20;->**<mark style="color:red;">**B페이지의**</mark> <mark style="color:red;">**onStartPage() 를 만나면 A페이지의 logScreen이벤트 전송.**</mark>&#x20;

위의 형태의 페이지 분석 호출 방식을 유념하여 페이지분석 코드를 삽입 해 주세요.
{% endhint %}

### Android

페이지 분석을 위해서는 각 화면의 이동시에 호출되는 Callback 함수에 다음과 같은 코드의 적용이 필요합니다.

페이지 진입시

{% tabs %}
{% tab title="Java" %}

```java
DOT.onStartPage(this);
```

{% endtab %}

{% tab title="kotlin" %}

```kotlin
 DOT.onStartPage(this)
```

{% endtab %}
{% endtabs %}

### Android Hybrid App을 위한 설정 추가

Hybrid App인 경우에만 적용하면 되는 설정으로, WebView로 표시한 웹페이지 내에서 발생하는 이벤트를 측정하기 위해 필요합니다. 웹뷰로 불러온 페이지를 감지할 수 있도록 다음과 같이 `setWebView` 함수를 호출해주세요.

{% tabs %}
{% tab title="Java" %}

```java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    WebView webView = findViewById(R.id.web_view);
    ...
    // SDK 호출
    DOT.setWebView(webView);
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val webView : WebView = findViewById(R.id.web_view)
    ...
    // SDK 호출
    DOT.setWebView(webView)
    }
```

{% endtab %}
{% endtabs %}

그리고 `WebViewClient` 의 각각의 콜백에 아래와 같이 적용해주세요.

{% tabs %}
{% tab title="Java" %}

```java
webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        // 1. document 에 DOT 객체 주입.
        WiseLog.d("onPageStarted" + url );
        DOT.injectSdkToHtmlDocument(view,true);
        super.onPageStarted(view,url,favicon);
    } 

    @Override
    public void onPageFinished(WebView view, String url) {
        WiseLog.d("onPageFinished" + url );
        DOT.injectJavascriptWithDomSearch(view,url,true);
        super.onPageFinished(view, url);
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
...
webView.webViewClient = object : WebViewClient() {
      fun onPageStarted(view: WebView?, url: String, favicon: Bitmap?) {
        // 1. document 에 DOT 객체 주입.
        WiseLog.d("onPageStarted$url")
        DOT.injectSdkToHtmlDocument(view)
        super.onPageStarted(view, url, favicon)
    }

    fun onPageFinished(view: WebView?, url: String) {
        WiseLog.d("onPageFinished$url")
        DOT.injectJavascriptWithDomSearch(view, url, true)
        super.onPageFinished(view, url)
    }
}
```

{% endtab %}
{% endtabs %}

### iOS

각 ViewController 이동 시에 호출되는 delegate 함수에 다음과 같이 기본적인 페이지 분석을 위한 코드를 적용합니다.

{% tabs %}
{% tab title="swift" %}

```swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    DOT.onStartPage()
}
```

{% endtab %}

{% tab title="objective-C" %}

```objectivec
- (void)viewWillAppear:(BOOL)animated {
	[super viewWillAppear:animated];
	[DOT onStartPage];
}
```

{% endtab %}
{% endtabs %}

### iOS Hybrid App을 위한 설정 추가

Hybrid 앱의 경우 앱 내에서 WebView 를 사용하여 웹 컨텐츠를 서비스 하기도 합니다. 이와 같이 Webview 에 의해서 보여지는 웹 컨텐츠의 경우에는 위에서 설명된 Native 화면과는 다른 방식으로 동작하기 때문에, 별도의 분석 코드 적용이 필요합니다. 분석 대상 앱이 만약 Hybrid 앱인 경우에는 아래의 코드를 참고하여 `웹 컨텐츠도 분석`할 수 있도록 적용을 해야합니다.

앱내에서 사용할 `WKWebView`의 `Delegate` 함수에 아래와 같이 분석코드를 적용합니다.

{% tabs %}
{% tab title="Swift" %}

```swift
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;
              }          
               ...
         }     
           ...
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
     [DOT injectSdkToHtmlDocument:webView withStartPage:true];
  }

- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
     [DOT injectSdkToHtmlDocument:webView withStartPage:false];
   }
 
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"2. didFinishNavigation");
      [DOT injectJavascriptWithDomSearch:webView isOnPageFinished:true];
    }

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
   if([@"jscall-dot" isEqualToString:navigationAction.request.URL.scheme]) {
      NSURLRequest *request = navigationAction.request;
      decisionHandler(WKNavigationActionPolicyCancel);
       [DOT setWkWebView:webView reqeust:request];
       return;

   }
}
```

{% endtab %}
{% endtabs %}

모바일앱내 웹뷰와 PC 혹은 모바일웹뷰로 동시에 사용하는 화면인 경우 아래와 같은 웹킷뷰를 포함한 viewController의 `viewWillApeear`에 아래와 같이 적용해주세요.

{% tabs %}
{% tab title="Swift" %}

```swift
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"
         }
     }
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
- (void)viewWillAppear:(BOOL)animated {
 [super viewWillAppear:animated];
 [self.webView evaluateJavaScript:@“navigator.userAgent” completionHandler:^(NSString *aUserAgent, NSError *aError) {
     NSString *sCustomUserAgent = @” RW2SDK”;
     if (aUserAgent.length > 0 && aError == nil) {
       sCustomUserAgent = [NSString stringWithFormat:@“%@ %@“, aUserAgent, sCustomUserAgent];
     }
     self.webView.customUserAgent = sCustomUserAgent;
   }];
}
```

{% endtab %}
{% endtabs %}

### React-Native

사용하는 라우터의 location 정보가 바뀔때마다 onStartPage를 호출 해 주어야 합니다. 아래는 React Navigation 라이브러리를 사용할때의 예제입니다.

{% tabs %}
{% tab title="App.js" %}

```javascript
import * as React from 'react';
import {NavigationContainer} from '@react-navigation/native';

const App = () => {

const navigationRef = useRef();

  return (
    <NavigationContainer
      ref={navigationRef}
      onStateChange={async () => {
   
     /* Activity 감지를 위한 예제 코드 */
      NativeModules.DotReactBridge != null &&
        /*로케이션 정보가 바뀔때마다 onStartPage 호출*/
        (NativeModules.DotReactBridge.onStartPage(),    
        NativeModules.DotReactBridge.logScreen(
          JSON.stringify({
            event: /*페이지 custom 이벤트명*/,
            pi: /*location 정보*/,
          }),
        ));
    }}>
  <Stack.Navigator>
    <Stack.Screen
      name="Main"
      component={Main}
    />
    <Stack.Screen
      name="Login"
      component={Login}
    />
  </Stack.Navigator>
</NavigationContainer>
  );
};

export default App;
```

{% endtab %}
{% endtabs %}

### ReactNative Hybrid App을 위한 설정 추가

Hybrid App인 경우에만 적용하면 되는 설정으로, WebView로 표시한 웹페이지 내에서 발생하는 이벤트를 측정하기 위해 필요합니다. 웹뷰로 불러온 페이지를 감지할 수 있도록 webview 컴포넌트에 다음과 같이  `onLoadStart` 와 `onMessage` 를 설정 해 줍니다.

{% tabs %}
{% tab title="WebView 설정" %}

```javascript
onLoadStart={(syntheticEvent)=>{ 
	if( NativeModules.DotReactBridge != null ){  
	/**
	웹 페이지가 로딩 시작될때, onStartPage 호출 
	**/
	NativeModules.DotReactBridge.onStartPage(); 
	} 
}}   


onMessage={(event) => { 
	if( event.nativeEvent.data !== undefined ){
	// 데이터 수신은 string으로 전달되므로 json으로 변환 
	let webData = JSON.parse(event.nativeEvent.data);
		if( webData.method ){
			switch(webData.method){
			
			// setUser call
			case "setUser" : 
			NativeModules.DotReactBridge.setUser(JSON.stringify(webData.data)); 	
			break;
			
			// logEvent call 
			case "logEvent" : 
			NativeModules.DotReactBridge.logEvent(JSON.stringify(webData.data)); 	
			break;
			
			// logScreen call 
			case "logScreen" : 
			NativeModules.DotReactBridge.logScreen(JSON.stringify(webData.data));
			break;
			
			// logPurchase	
			case "logPurchase" : 
			NativeModules.DotReactBridge.logPurchase(JSON.stringify(webData.data));
			break;
			} 
		}  
	} 
}}
```

{% endtab %}
{% endtabs %}

### Flutter

고객사 앱에서 페이지 네비게이션으로 `RouteObserver Class`를 사용하고 있다면 아래와 같이 적용해 주세요.

{% tabs %}
{% tab title="MyRouteObserver.dart(sample)" %}

```javascript
class MyRouteObserver extends RouteObserver<PageRoute<dynamic>> {
  

  void _sendScreenView(PageRoute<dynamic> route) {
    var screenName = route.settings.name;
     
    // 화면 전환 시점에 onStartPage 함수 호출.  
    DOT.onStartPage();
    print('DOT.onStartPage() Called  $screenName');
     
  }

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPush(route, previousRoute);
    if (route is PageRoute) {
      _sendScreenView(route);
    }
  } 

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPop(route, previousRoute);
    if (previousRoute is PageRoute && route is PageRoute) {
      _sendScreenView(previousRoute);
    }
  }
}
```

{% endtab %}
{% endtabs %}

화면 이동에 대한 페이지 분석코드를 작성할 때의 예제를 아래에서 확인할 수 있습니다.  screen2에서 screen3으로 화면 전환을 했을 때 위에 기재된 `MyRouteObserver`에 `onStartPage()`가 먼저 호출 되고, screen 에서 build가 호출 되고 `DOT.logScreen` 호출 순서로 동작합니다.

{% tabs %}
{% tab title="dart(sample)" %}

```javascript
class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //페이지 관련 정보 세팅
    var screen = {};
    screen["pi"] = "MAIN";
    DOT.logScreen(screen);
    
    return Scaffold(appBar: AppBar(), body: Center(child: Text('Screen 2')));
  }
}

class Screen3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //페이지 관련 정보 세팅
    var screen = {};
    screen["pi"] = "DTL";
    DOT.logScreen(screen);

    return Scaffold(appBar: AppBar(), body: Center(child: Text('Screen 3')));
  }
}
```

{% endtab %}
{% endtabs %}

### Website

페이지 분석은 웹페이지가 **로딩 완료된 시점**에 SDK가 제공하는 함수를 호출하여 쉽게 수행할 수 있습니다. Javascript 타입의 경우, 공통적으로 모든 소스 파일에서 참조하는 공통 footer 파일에 적용하는 것을 권장합니다. JSX 타입의 경우, 위의 SDK 초기화 작업에서와 마찬가지로 컴포넌트 상속 관계를 응용하여 `ComponentDidMount` 함수 또는 두번째 인자가 빈배열(`[]`)인 `useEffect`에 적용하는 것을 권장합니다.

{% tabs %}
{% tab title="JavaScript" %}

```javascript
<script  type="text/javascript"  defer>
	WDOT.logScreen(window.WDOTParam || {});
</script>
```

{% endtab %}

{% tab title="JSX" %}

```jsx
componentDidMount() {
    WDOT.logScreen({});
}
```

{% endtab %}
{% endtabs %}
