# Phase 7: Event Lookup & Parameter Library Web App

Google Apps Script를 활용한 Event Taxonomy Sheet 기반 업무 지원용 앱 배포.

## Objectives

1. Event Taxonomy 데이터 조회 앱
2. 실시간 파라미터 참조 도구
3. 비개발자용 Self-service 도구
4. 팀 간 일관된 이벤트 정보 공유

## App Architecture

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Google Sheets  │────▶│  Apps Script    │────▶│   Web App       │
│  (Taxonomy DB)  │     │  (Backend)      │     │  (Frontend)     │
└─────────────────┘     └─────────────────┘     └─────────────────┘
```

## Google Sheets Data Source

### Required Sheets
- Events Master
- Parameters Reference
- Custom Definitions
- Platform Mapping

### Column Requirements
→ Phase 4 참조: [phase4-taxonomy.md](phase4-taxonomy.md)

## Apps Script Setup

### 1. Project Creation
```
1. Google Sheets 열기
2. Extensions > Apps Script
3. 프로젝트 이름 설정
```

### 2. Core Functions

#### Data Retrieval
```javascript
function getEventsData() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Events Master');
  const data = sheet.getDataRange().getValues();
  const headers = data[0];
  
  return data.slice(1).map(row => {
    const obj = {};
    headers.forEach((header, i) => {
      obj[header] = row[i];
    });
    return obj;
  });
}

function getParametersData() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Parameters Reference');
  const data = sheet.getDataRange().getValues();
  const headers = data[0];
  
  return data.slice(1).map(row => {
    const obj = {};
    headers.forEach((header, i) => {
      obj[header] = row[i];
    });
    return obj;
  });
}
```

#### Search Function
```javascript
function searchEvents(query) {
  const events = getEventsData();
  const searchTerm = query.toLowerCase();
  
  return events.filter(event => 
    event.event_name.toLowerCase().includes(searchTerm) ||
    event.event_category.toLowerCase().includes(searchTerm) ||
    event.notes.toLowerCase().includes(searchTerm)
  );
}

function getEventDetails(eventName) {
  const events = getEventsData();
  const params = getParametersData();
  
  const event = events.find(e => e.event_name === eventName);
  if (!event) return null;
  
  const eventParams = event.parameters.split(',').map(p => p.trim());
  const paramDetails = params.filter(p => 
    eventParams.includes(p.parameter_name)
  );
  
  return {
    event: event,
    parameters: paramDetails
  };
}
```

### 3. Web App Handler

```javascript
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('index')
    .setTitle('GTM Event Lookup')
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

function doPost(e) {
  const action = e.parameter.action;
  
  switch(action) {
    case 'search':
      return ContentService.createTextOutput(
        JSON.stringify(searchEvents(e.parameter.query))
      ).setMimeType(ContentService.MimeType.JSON);
      
    case 'details':
      return ContentService.createTextOutput(
        JSON.stringify(getEventDetails(e.parameter.eventName))
      ).setMimeType(ContentService.MimeType.JSON);
      
    default:
      return ContentService.createTextOutput(
        JSON.stringify({error: 'Invalid action'})
      ).setMimeType(ContentService.MimeType.JSON);
  }
}
```

### 4. HTML Frontend (index.html)

```html
<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <style>
    body { font-family: 'Roboto', sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
    .search-box { width: 100%; padding: 12px; font-size: 16px; margin-bottom: 20px; }
    .event-card { border: 1px solid #ddd; padding: 16px; margin: 10px 0; border-radius: 8px; }
    .event-name { font-size: 18px; font-weight: bold; color: #1a73e8; }
    .param-badge { background: #e8f0fe; color: #1967d2; padding: 4px 8px; border-radius: 4px; margin: 2px; display: inline-block; }
    .category { color: #5f6368; font-size: 14px; }
    .priority-p1 { border-left: 4px solid #ea4335; }
    .priority-p2 { border-left: 4px solid #fbbc04; }
    .priority-p3 { border-left: 4px solid #34a853; }
  </style>
</head>
<body>
  <h1>🏷️ GTM Event Lookup</h1>
  <input type="text" class="search-box" id="searchInput" placeholder="이벤트명 또는 카테고리 검색...">
  <div id="results"></div>
  
  <script>
    const searchInput = document.getElementById('searchInput');
    const results = document.getElementById('results');
    
    searchInput.addEventListener('input', debounce(function() {
      const query = this.value;
      if (query.length < 2) {
        results.innerHTML = '';
        return;
      }
      
      google.script.run
        .withSuccessHandler(displayResults)
        .searchEvents(query);
    }, 300));
    
    function displayResults(events) {
      results.innerHTML = events.map(event => `
        <div class="event-card priority-${event.priority.toLowerCase()}">
          <div class="event-name">${event.event_name}</div>
          <div class="category">${event.event_category} | ${event.priority}</div>
          <div style="margin-top: 10px;">
            ${event.parameters.split(',').map(p => 
              `<span class="param-badge">${p.trim()}</span>`
            ).join('')}
          </div>
          <div style="margin-top: 10px; color: #5f6368;">${event.notes}</div>
        </div>
      `).join('');
    }
    
    function debounce(func, wait) {
      let timeout;
      return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
      };
    }
  </script>
</body>
</html>
```

## Deployment

### 1. Deploy as Web App
```
1. Deploy > New deployment
2. Type: Web app
3. Execute as: Me
4. Access: Anyone within organization (또는 Anyone)
5. Deploy
```

### 2. Get Web App URL
```
배포 후 제공되는 URL 복사
https://script.google.com/macros/s/[ID]/exec
```

### 3. Share with Team
- URL을 Notion/Slack에 공유
- 북마크 권장

## Features Roadmap

### Phase 1 (MVP)
- [x] 이벤트 검색
- [x] 파라미터 조회
- [x] 우선순위 필터

### Phase 2
- [ ] DataLayer 코드 스니펫 복사
- [ ] 플랫폼별 코드 예시
- [ ] 최근 조회 히스토리

### Phase 3
- [ ] 이벤트 추가/수정 폼
- [ ] 변경 이력 추적
- [ ] Slack 알림 연동

## Maintenance

### Data Update
1. Google Sheets 원본 데이터 수정
2. Web App 자동 반영 (실시간)

### Code Update
1. Apps Script 수정
2. Deploy > Manage deployments
3. New version 배포

### Backup
- Google Sheets 자동 버전 히스토리
- 주기적 수동 백업 권장

## Access Control

| Role | Access Level |
|------|--------------|
| Admin | 시트 편집 + 스크립트 수정 |
| Editor | 시트 편집 |
| Viewer | Web App 조회만 |

## Troubleshooting

| Issue | Solution |
|-------|----------|
| 앱 로딩 느림 | 데이터 캐싱 구현 |
| 검색 결과 없음 | 검색어 확인, 데이터 존재 확인 |
| 권한 오류 | 배포 설정에서 접근 권한 확인 |
| 데이터 미반영 | 시트 새로고침, 캐시 클리어 |

## Integration with Notion

Web App URL을 Notion에 embed:
```
/embed [Web App URL]
```

또는 iframe으로 직접 삽입.
