commit f34e0e085a57201e3968ec13137def3a1010576e Author: 王源 Date: Mon Oct 19 19:50:06 2026 +0800 feat: add traffic intelligence toolkit diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ccd153 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Traffic Information & Tracking Link Generator + +纯静态的 AgentStage 报告框架,无构建依赖。 + +## 页面 + +- `index.html`:工具入口 +- `channel-recommendation.html`:包名、品类、国家 → 渠道优先级建议 +- `link-generator.html`:自投平台 Click / Impression 链接生成 + +## 可维护数据 + +- `assets/data/channel-rules.js`:品类、国家、区域和渠道评分规则 +- `assets/data/link-templates.js`:媒体宏与链接参数模板 + +当前渠道评分是用于验证页面和解释结构的 v0.1 规则基线,并非真实绩效模型。下一阶段可接入历史消耗、转化、渠道 Active/Pause 状态及包名国家命中数据。 + +## 本地预览 + +静态页面使用相对路径,可直接打开;若浏览器限制本地资源,可在目录中运行一次性静态服务器: + +```sh +python3 -m http.server 8080 +``` + +然后访问 `http://localhost:8080/`。 diff --git a/assets/channel.js b/assets/channel.js new file mode 100644 index 0000000..4b15ed7 --- /dev/null +++ b/assets/channel.js @@ -0,0 +1,121 @@ +(() => { + const data = window.CHANNEL_RULES; + if (!data) return; + + const form = document.getElementById('recommendationForm'); + const category = document.getElementById('category'); + const country = document.getElementById('country'); + const packageName = document.getElementById('packageName'); + const message = document.getElementById('formMessage'); + const empty = document.getElementById('resultEmpty'); + const content = document.getElementById('resultContent'); + const list = document.getElementById('resultList'); + const summary = document.getElementById('querySummary'); + const resetBtn = document.getElementById('resetBtn'); + + data.categories.forEach((item) => category.add(new Option(item.label, item.value))); + data.countries.forEach(([code, name]) => country.add(new Option(`${name} · ${code}`, code))); + + const categoryLabel = (value) => data.categories.find((item) => item.value === value)?.label || value; + const countryLabel = (value) => { + const item = data.countries.find(([code]) => code === value); + return item ? `${item[1]} · ${item[0]}` : value; + }; + + function scoreChannel(channel, query) { + let score = channel.base; + const reasons = [`基础能力 ${channel.base} 分`]; + const region = data.regionMap[query.country]; + + if (channel.categories.includes(query.category)) { + score += 35; + reasons.push(`适配「${categoryLabel(query.category)}」品类`); + } else if (channel.categories.includes('other')) { + score += 10; + reasons.push('支持通用品类测试'); + } + + if (channel.countries.includes(query.country)) { + score += 30; + reasons.push(`明确覆盖 ${query.country}`); + } else if (region && channel.regions.includes(region)) { + score += 24; + reasons.push(`覆盖 ${region} 区域`); + } else if (channel.countries.includes('GLOBAL')) { + score += 18; + reasons.push('具备全球流量覆盖'); + } + + if (query.os === 'ALL' || channel.os.includes(query.os)) { + score += 10; + reasons.push(query.os === 'ALL' ? '同时支持 Android / iOS' : `支持 ${query.os === 'AOS' ? 'Android' : 'iOS'}`); + } + + const lowerPkg = query.pkg.toLowerCase(); + const hint = channel.pkgHints.find((word) => lowerPkg.includes(word)); + if (hint) { + score += 5; + reasons.push(`包名特征命中「${hint}」`); + } + + return { ...channel, score: Math.min(score, 100), reasons }; + } + + function priority(score, index) { + if (index === 0 || score >= 80) return ['P1', '优先测试', 'priority-high']; + if (score >= 65) return ['P2', '建议测试', 'priority-mid']; + return ['P3', '补充候选', 'priority-low']; + } + + function render(query) { + const results = data.channels.map((channel) => scoreChannel(channel, query)).sort((a, b) => b.score - a.score).slice(0, 6); + summary.innerHTML = `
PACKAGE${escapeHtml(query.pkg)}
CATEGORY${escapeHtml(categoryLabel(query.category))}
GEO${escapeHtml(countryLabel(query.country))}
`; + list.innerHTML = results.map((item, index) => { + const [level, label, className] = priority(item.score, index); + return `
+
${String(index + 1).padStart(2, '0')}
+

${escapeHtml(item.name)}

${escapeHtml(item.type)}
+
${item.reasons.slice(1, 4).map((reason) => `${escapeHtml(reason)}`).join('')}
+

${escapeHtml(item.strengths.join(' · '))}

+
+
${item.score}/100
${level} · ${label}
+
`; + }).join(''); + empty.classList.add('hidden'); + content.classList.remove('hidden'); + resetBtn.classList.remove('hidden'); + } + + function escapeHtml(value) { + return String(value).replace(/[&<>"']/g, (char) => ({ '&':'&', '<':'<', '>':'>', '"':'"', "'":''' })[char]); + } + + form.addEventListener('submit', (event) => { + event.preventDefault(); + const pkg = packageName.value.trim(); + if (!pkg || !category.value || !country.value) { + message.textContent = '请完整填写包名、产品品类和投放国家。'; + return; + } + message.textContent = ''; + const os = form.querySelector('input[name="os"]:checked').value; + render({ pkg, category: category.value, country: country.value, os }); + }); + + document.getElementById('sampleBtn').addEventListener('click', () => { + packageName.value = 'com.example.finance'; + category.value = 'finance'; + country.value = 'ID'; + form.querySelector('input[name="os"][value="AOS"]').checked = true; + message.textContent = ''; + }); + + resetBtn.addEventListener('click', () => { + form.reset(); + message.textContent = ''; + content.classList.add('hidden'); + resetBtn.classList.add('hidden'); + empty.classList.remove('hidden'); + packageName.focus(); + }); +})(); diff --git a/assets/common.js b/assets/common.js new file mode 100644 index 0000000..3823200 --- /dev/null +++ b/assets/common.js @@ -0,0 +1,12 @@ +(() => { + document.querySelectorAll('[data-year]').forEach((node) => { + node.textContent = new Date().getFullYear(); + }); + + document.querySelectorAll('a[href]').forEach((link) => { + if (link.hostname && link.hostname !== window.location.hostname) { + link.target = '_blank'; + link.rel = 'noopener noreferrer'; + } + }); +})(); diff --git a/assets/data/channel-rules.js b/assets/data/channel-rules.js new file mode 100644 index 0000000..70cdc02 --- /dev/null +++ b/assets/data/channel-rules.js @@ -0,0 +1,36 @@ +window.CHANNEL_RULES = { + version: '0.1', + categories: [ + { value: 'finance', label: '金融 / 借贷 / 交易' }, + { value: 'gaming', label: '游戏' }, + { value: 'ecommerce', label: '电商 / 购物' }, + { value: 'social', label: '社交 / 直播' }, + { value: 'entertainment', label: '娱乐 / 短剧 / 视频' }, + { value: 'utility', label: '工具 / 效率' }, + { value: 'travel', label: '旅游 / 出行' }, + { value: 'food', label: '餐饮 / 本地生活' }, + { value: 'other', label: '其他' } + ], + countries: [ + ['US','美国'],['CA','加拿大'],['MX','墨西哥'],['BR','巴西'],['AR','阿根廷'],['CO','哥伦比亚'], + ['IN','印度'],['ID','印度尼西亚'],['PH','菲律宾'],['TH','泰国'],['VN','越南'],['MY','马来西亚'],['SG','新加坡'], + ['SA','沙特阿拉伯'],['AE','阿联酋'],['EG','埃及'],['TR','土耳其'],['ZA','南非'],['NG','尼日利亚'], + ['RU','俄罗斯'],['GB','英国'],['DE','德国'],['FR','法国'],['ES','西班牙'],['IT','意大利'],['AU','澳大利亚'],['JP','日本'],['KR','韩国'] + ], + regionMap: { + US:'NA', CA:'NA', MX:'LATAM', BR:'LATAM', AR:'LATAM', CO:'LATAM', + IN:'SASIA', ID:'SEA', PH:'SEA', TH:'SEA', VN:'SEA', MY:'SEA', SG:'SEA', + SA:'MENA', AE:'MENA', EG:'MENA', TR:'MENA', ZA:'AFRICA', NG:'AFRICA', + RU:'EEA', GB:'EU', DE:'EU', FR:'EU', ES:'EU', IT:'EU', AU:'OCEANIA', JP:'NEA', KR:'NEA' + }, + channels: [ + { name:'Mintegral', type:'自投媒体', base:20, categories:['gaming','utility','ecommerce','entertainment'], countries:['GLOBAL'], regions:['SEA','SASIA','LATAM','MENA','EU','NA'], os:['AOS','IOS'], strengths:['程序化流量覆盖广','App 场景适配度高'], pkgHints:['game','play','shop','video'] }, + { name:'Bigo Ads', type:'自投媒体', base:18, categories:['social','entertainment','gaming','ecommerce'], countries:['ID','PH','TH','VN','MY','BR','MX','SA','AE'], regions:['SEA','LATAM','MENA'], os:['AOS','IOS'], strengths:['社交娱乐流量场景','东南亚与新兴市场覆盖'], pkgHints:['live','chat','video','social'] }, + { name:'Kwai for Business', type:'自投媒体', base:18, categories:['ecommerce','entertainment','gaming','social','finance'], countries:['BR','MX','ID','PH','SA','AE'], regions:['LATAM','SEA','MENA'], os:['AOS','IOS'], strengths:['短视频内容场景','拉美区域覆盖'], pkgHints:['video','shop','live','game'] }, + { name:'MediaGO', type:'自投媒体', base:17, categories:['finance','ecommerce','utility','travel'], countries:['GLOBAL'], regions:['NA','EU','EEA','SEA','LATAM'], os:['AOS','IOS'], strengths:['原生广告场景','金融与电商候选流量'], pkgHints:['finance','loan','credit','bank','shop'] }, + { name:'NewsBreak', type:'自投媒体', base:16, categories:['finance','ecommerce','utility','travel','food'], countries:['US','CA'], regions:['NA'], os:['AOS','IOS'], strengths:['北美资讯内容场景','本地化受众触达'], pkgHints:['news','finance','food','local'] }, + { name:'Adsterra', type:'自投媒体', base:15, categories:['gaming','finance','utility','entertainment'], countries:['GLOBAL'], regions:['SEA','SASIA','LATAM','MENA','AFRICA','EEA'], os:['AOS','IOS'], strengths:['多广告形式覆盖','新兴市场可扩量'], pkgHints:['bet','casino','loan','vpn','game'] }, + { name:'SmartyAds', type:'自投媒体', base:14, categories:['gaming','ecommerce','utility','entertainment','other'], countries:['GLOBAL'], regions:['NA','EU','SEA','LATAM','MENA'], os:['AOS','IOS'], strengths:['程序化流量补充','支持多种媒体宏'], pkgHints:['app','mobile','game','shop'] }, + { name:'Runto', type:'代理渠道', base:13, categories:['finance','gaming','ecommerce','social','utility','travel','food','other'], countries:['GLOBAL'], regions:['SEA','SASIA','LATAM','MENA','AFRICA','EEA','EU'], os:['AOS','IOS'], strengths:['历史包名与国家池较丰富','适合作为代理渠道候选'], pkgHints:[] } + ] +}; diff --git a/assets/data/link-templates.js b/assets/data/link-templates.js new file mode 100644 index 0000000..c9ce885 --- /dev/null +++ b/assets/data/link-templates.js @@ -0,0 +1,57 @@ +window.LINK_TEMPLATES = [ + { + name:'Mintegral', platformCode:'M_API_Self_Mintegral', status:'已配置', + macros:[['{click_id}','媒体点击 ID'],['{offer_name}','Offer 名称'],['{ad_id}','素材 ID'],['{ad_name}','素材名称'],['{affiliate_id}','子渠道 ID'],['{idfa}','iOS 广告标识'],['{gaid}','Google 广告标识'],['{device_os}','设备系统'],['{country_code}','ISO 国家码'],['{ip}','设备 IP'],['{ua}','User Agent']], + links:{ + click:{endpoint:'https://trident.bigpinggo.com/click', mappings:{clickid:'{click_id}',offer_name:'{offer_name}',creative_id:'{ad_id}',creative_name:'{ad_name}',affiliate_id:'{affiliate_id}',idfa:'{idfa}',gaid:'{gaid}',uagent:'{ua}',os_platform:'{device_os}',os_version:'{os_version}',device_model:'{device_model}',ip:'{ip}',country_code:'{country_code}',ext:'{uuid}',rta_token:'{rta_token}'}}, + imp:{endpoint:'https://typhoon.bigpinggo.com/imp', mappings:{clickid:'{impression_id}',offer_name:'{offer_name}',creative_id:'{ad_id}',creative_name:'{ad_name}',affiliate_id:'{affiliate_id}',idfa:'{idfa}',gaid:'{gaid}',uagent:'{ua}',os_platform:'{device_os}',device_model:'{device_model}',ip:'{ip}',country_code:'{country_code}',ext:'{uuid}'}} + } + }, + { + name:'Bigo', platformCode:'M_API_Self_Bigo', status:'已配置', + macros:[['__SID__','广告请求 / 点击 ID'],['__APPID__','推广 App ID'],['__CAMPAIGN_ID__','广告系列 ID'],['__CAMPAIGN_NAME__','广告系列名称'],['__AD_ID__','广告 ID'],['__AD_NAME__','广告名称'],['__IDFA__','iOS 广告标识'],['__GAID__','Google 广告标识'],['__IP__','设备 IP'],['__OS__','操作系统'],['__PUBLISHER_ID__','子渠道 ID']], + links:{ + click:{endpoint:'https://trident.bigpinggo.com/click', mappings:{clickid:'__SID__',offer_name:'__CAMPAIGN_NAME__',creative_id:'__AD_ID__',creative_name:'__AD_NAME__',affiliate_id:'__PUBLISHER_ID__',idfa:'__IDFA__',gaid:'__GAID__',os_platform:'__OS__',device_model:'__DEVICE_MODEL__',ip:'__IP__',country_code:'',ext:'__AD_EXT__',rta_token:'{rta_token}'}}, + imp:{endpoint:'https://typhoon.bigpinggo.com/imp', mappings:{clickid:'imp__SID__',offer_name:'__CAMPAIGN_NAME__',creative_id:'__AD_ID__',creative_name:'__AD_NAME__',affiliate_id:'__PUBLISHER_ID__',idfa:'__IDFA__',gaid:'__GAID__',os_platform:'__OS__',device_model:'__DEVICE_MODEL__',ip:'__IP__',country_code:'',ext:'__AD_EXT__'}} + } + }, + { + name:'Kwai', platformCode:'M_API_Self_Kwai_NB', status:'已配置', + macros:[['__CALLBACK__','Click ID'],['__GAID1__','Google 广告标识'],['__IDFA__','iOS 广告标识'],['__IP__','设备 IP'],['__UA__','设备 User Agent'],['__CMPNID__','广告计划 ID'],['__ADSETID__','广告组 ID'],['__ADID__','广告 ID']], + links:{ + click:{endpoint:'https://trident.bigpinggo.com/click', mappings:{clickid:'__CALLBACK__',offer_name:'__CMPNID__',creative_id:'__ADSETID__',creative_name:'__ADID__',affiliate_id:'__ADSETID__',idfa:'__IDFA__',gaid:'__GAID1__',uagent:'__UA__',ip:'__IP__',country_code:'',ext:'',rta_token:'{rta_token}'}}, + imp:{endpoint:'https://typhoon.bigpinggo.com/imp', mappings:{clickid:'__CALLBACK__',offer_name:'__CMPNID__',creative_id:'__ADSETID__',creative_name:'__ADID__',affiliate_id:'__CMPNID__',idfa:'__IDFA__',gaid:'__GAID1__',uagent:'__UA__',ip:'__IP__',country_code:'',ext:''}} + } + }, + { + name:'MediaGO', platformCode:'M_API_Self_Mediago', status:'已配置', + macros:[['{TRACKING_ID}','完整用户旅程 Tracking ID'],['{CLICK_ID}','点击 ID'],['{ADVERTISING_ID}','通用广告标识'],['{ANDROID_ID}','Android 设备 ID'],['{AD_SET_ID}','广告组 / Affiliate ID']], + links:{ + click:{endpoint:'https://trident.bigpinggo.com/click', mappings:{clickid:'{TRACKING_ID}',offer_name:'',creative_id:'',creative_name:'{AD_SET_ID}',affiliate_id:'{AD_SET_ID}',idfa:'',gaid:'{ADVERTISING_ID}',android_id:'{ANDROID_ID}',country_code:'',ext:'',rta_token:''}}, + imp:{endpoint:'https://typhoon.bigpinggo.com/imp', mappings:{clickid:'{TRACKING_ID}',affiliate_id:'{AD_SET_ID}',gaid:'{ADVERTISING_ID}',android_id:'{ANDROID_ID}',country_code:'',ext:''}} + } + }, + { + name:'NewsBreak', platformCode:'A_API_SPDragon', status:'待业务复核', + macros:[['__CALLBACK_PARAM__','平台唯一回调参数'],['__CAMPAIGN_ID__','Campaign ID'],['__CAMPAIGN_NAME__','Campaign 名称'],['__FLIGHT_ID__','Ad Set ID'],['__FLIGHT_NAME__','Ad Set 名称'],['__CREATIVE_ID__','Creative ID'],['__CREATIVE_NAME__','Creative 名称'],['__ADID__','GAID'],['__IDFA__','IDFA'],['__OS__','操作系统']], + links:{ + click:{endpoint:'https://trident.bigpinggo.com/l/click', mappings:{clickid:'__CALLBACK_PARAM__',offer_name:'__CAMPAIGN_NAME__',creative_id:'__CREATIVE_ID__',creative_name:'__CREATIVE_NAME__',affiliate_id:'__FLIGHT_ID_____FLIGHT_NAME__',idfa:'__IDFA__',gaid:'__ADID__',os_platform:'__OS__',country_code:'',ext:'',rta_token:'{rta_token}'}}, + imp:{endpoint:'https://typhoon.bigpinggo.com/imp', mappings:{clickid:'__CALLBACK_PARAM__',offer_name:'__CAMPAIGN_NAME__',creative_id:'__CREATIVE_ID__',creative_name:'__CREATIVE_NAME__',affiliate_id:'__FLIGHT_ID_____FLIGHT_NAME__',idfa:'__IDFA__',gaid:'__ADID__',os_platform:'__OS__',country_code:'',ext:''}} + } + }, + { + name:'Adsterra', platformCode:'P_API_Adsterra', status:'已配置', + macros:[['##SUB_ID_SHORT(action)##','Click ID'],['##PLACEMENT_ID##','广告位 / Affiliate ID'],['##BANNER_ID##','素材 ID'],['##USERAGENT##','User Agent'],['##USER_OS##','设备系统'],['##USER_OS_VER##','系统版本'],['##REMOTE_IP##','设备 IP'],['##COUNTRY_CODE##','国家码']], + links:{click:{endpoint:'https://trident.bigpinggo.com/l/click', mappings:{clickid:'##SUB_ID_SHORT(action)##',offer_name:'',creative_id:'##BANNER_ID##',creative_name:'',affiliate_id:'##PLACEMENT_ID##',uagent:'##USERAGENT##',os_platform:'##USER_OS##',os_version:'##USER_OS_VER##',ip:'##REMOTE_IP##',country_code:'##COUNTRY_CODE##',ext:''}}} + }, + { + name:'SmartyAds', platformCode:'M_API_Self_Smartyads', status:'已配置', + macros:[['[CLICK_ID]','Click ID'],['[TIMESTAMP]','UNIX 时间戳'],['[CAMPAIGN_ID]','Campaign ID'],['[CREATIVE_ID]','素材 ID'],['[CREATIVE_NAME]','素材名称'],['[APP_BUNDLE]','媒体 App Bundle'],['[IFA]','设备广告标识'],['[USER_AGENT]','User Agent'],['[OS]','操作系统'],['[IP]','设备 IP'],['[COUNTRY]','国家码']], + links:{click:{endpoint:'https://trident.bigpinggo.com/l/click', mappings:{clickid:'[CLICK_ID]_[TIMESTAMP]',offer_name:'[CAMPAIGN_ID]',creative_id:'[CREATIVE_ID]',creative_name:'[CREATIVE_NAME]',affiliate_id:'[APP_BUNDLE]',gaid:'[IFA]',uagent:'[USER_AGENT]',os_platform:'[OS]',os_version:'[OSV]',device_model:'[DEVICE_MAKE]',ip:'[IP]',country_code:'[COUNTRY]',ext:'[CLICK_ID]',rta_token:''}}} + }, + { + name:'Traffic Star', platformCode:'A_API_SPDragon', status:'待业务复核', + macros:[['{click_id}','S2S Click ID'],['{campaign_id}','Campaign ID'],['{creative_id}','素材 ID'],['{site_id}','站点 ID'],['{os}','操作系统'],['{device_type_id}','设备类型 ID'],['{ip}','设备 IP'],['{geo}','两位国家码'],['{format}','素材格式']], + links:{click:{endpoint:'https://trident.bigpinggo.com/l/click', mappings:{clickid:'{click_id}',offer_name:'{campaign_id}',creative_id:'{creative_id}',creative_name:'{format}',affiliate_id:'{site_id}',os_platform:'{os}',os_version:'{os_id}',device_model:'{device_type_id}',ip:'{ip}',country_code:'{geo}',ext:'',rta_token:''}}} + } +]; diff --git a/assets/link-generator.js b/assets/link-generator.js new file mode 100644 index 0000000..eb50235 --- /dev/null +++ b/assets/link-generator.js @@ -0,0 +1,142 @@ +(() => { + const templates = window.LINK_TEMPLATES; + if (!templates?.length) return; + + const $ = (id) => document.getElementById(id); + const platformSelect = $('platformSelect'); + const linkTypeSelect = $('linkTypeSelect'); + const mappingBody = $('mappingTableBody'); + const macroBody = $('macroTableBody'); + const output = $('urlOutput'); + const businessIds = ['advid','campid','pkg','platformCode','sanCampid','adsetId','countryCode']; + let state = { platformIndex:0, type:'click', mappings:{} }; + + $('templateCount').textContent = `${templates.length} 个平台模板`; + templates.forEach((template, index) => platformSelect.add(new Option(template.name, index))); + + const activeTemplate = () => templates[state.platformIndex]; + const activeLink = () => activeTemplate().links[state.type]; + + function loadPlatform() { + const template = activeTemplate(); + linkTypeSelect.innerHTML = ''; + Object.keys(template.links).forEach((type) => linkTypeSelect.add(new Option(type === 'click' ? 'Click Link' : 'Impression Link', type))); + state.type = Object.keys(template.links)[0]; + $('platformCode').value = template.platformCode; + $('platformStatus').innerHTML = `${template.status}`; + renderMacros(); + loadLink(); + } + + function loadLink() { + state.mappings = { ...activeLink().mappings }; + renderMappings(); + buildUrl(); + } + + function renderMacros() { + const query = $('macroSearch').value.trim().toLowerCase(); + const rows = activeTemplate().macros.filter(([macro, desc]) => `${macro} ${desc}`.toLowerCase().includes(query)); + macroBody.innerHTML = rows.length + ? rows.map(([macro, desc]) => `${escapeHtml(macro)}${escapeHtml(desc)}`).join('') + : '没有匹配的媒体宏'; + } + + function renderMappings() { + mappingBody.innerHTML = Object.entries(state.mappings).map(([key, value]) => `${escapeHtml(key)}`).join(''); + mappingBody.querySelectorAll('input').forEach((input) => input.addEventListener('input', () => { + state.mappings[input.dataset.key] = input.value; + buildUrl(); + })); + } + + function buildUrl() { + const link = activeLink(); + const campid = $('campid').value.trim(); + const pkg = $('pkg').value.trim(); + const type = state.type; + const params = []; + const addBusiness = (key, value) => params.push(`${key}=${encodeURIComponent(value)}`); + const addRaw = (key, value) => params.push(`${key}=${value}`); + + if (type === 'click') { + addBusiness('advid', $('advid').value.trim()); + addBusiness('campid', campid); + addBusiness('platform', $('platformCode').value.trim()); + addBusiness('pkg', pkg); + } else { + addBusiness('campid', campid); + addBusiness('pkg', pkg); + } + + Object.entries(state.mappings).forEach(([key, value]) => { + const finalValue = key === 'country_code' && $('countryCode').value.trim() + ? $('countryCode').value.trim().toUpperCase() + : value; + addRaw(key, finalValue); + }); + + if (type === 'click') { + if ($('sanCampid').value.trim()) addBusiness('san_campid', $('sanCampid').value.trim()); + if ($('adsetId').value.trim()) addBusiness('adset_id', $('adsetId').value.trim()); + addRaw('c_cto', '0'); + } else { + addRaw('at_tag', '2'); + } + + const url = `${link.endpoint}?${params.join('&')}`; + output.textContent = url; + $('urlLength').textContent = `${url.length} chars`; + + const missing = []; + if (!campid) missing.push('Campaign ID'); + if (!pkg) missing.push('Package Name'); + $('generatorMessage').textContent = missing.length ? `待填写:${missing.join('、')}` : ''; + } + + function resetGenerator() { + $('advid').value = '30'; + $('campid').value = ''; + $('pkg').value = ''; + $('platformCode').value = activeTemplate().platformCode; + $('sanCampid').value = ''; + $('adsetId').value = '-1'; + $('countryCode').value = ''; + loadLink(); + } + + async function copyUrl() { + if (!$('campid').value.trim() || !$('pkg').value.trim()) { + $('copyStatus').textContent = '请先补全必填参数'; + return; + } + try { + await navigator.clipboard.writeText(output.textContent); + } catch (_) { + const range = document.createRange(); + range.selectNodeContents(output); + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + document.execCommand('copy'); + selection.removeAllRanges(); + } + $('copyStatus').textContent = '已复制'; + const toast = $('toast'); + toast.textContent = '最终链接已复制到剪贴板'; + toast.classList.add('show'); + setTimeout(() => toast.classList.remove('show'), 1800); + } + + function escapeHtml(value) { + return String(value).replace(/[&<>"']/g, (char) => ({ '&':'&', '<':'<', '>':'>', '"':'"', "'":''' })[char]); + } + + platformSelect.addEventListener('change', () => { state.platformIndex = Number(platformSelect.value); loadPlatform(); }); + linkTypeSelect.addEventListener('change', () => { state.type = linkTypeSelect.value; loadLink(); }); + $('macroSearch').addEventListener('input', renderMacros); + businessIds.forEach((id) => $(id).addEventListener('input', buildUrl)); + $('resetGenerator').addEventListener('click', resetGenerator); + $('copyLink').addEventListener('click', copyUrl); + loadPlatform(); +})(); diff --git a/assets/styles.css b/assets/styles.css new file mode 100644 index 0000000..6cde094 --- /dev/null +++ b/assets/styles.css @@ -0,0 +1,11 @@ +@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Inter:wght@400;500;600;700;800&display=swap'); + +:root{--ink:#11231f;--muted:#66736f;--paper:#f4f3ee;--white:#fff;--line:#dcded8;--blue:#6f8cff;--blue-dark:#334ed0;--lime:#c8f55b;--lime-dark:#799d18;--orange:#ff8e55;--shadow:0 18px 50px rgba(18,35,31,.08);--radius:22px;--mono:'DM Mono',ui-monospace,SFMono-Regular,monospace;--sans:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif} +*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:14px;line-height:1.55}a{color:inherit;text-decoration:none}button,input,select{font:inherit}button{cursor:pointer}.shell{width:min(1180px,calc(100% - 48px));margin-inline:auto}.hidden{display:none!important} +.site-header{height:80px;padding:0 max(24px,calc((100vw - 1180px)/2));display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid rgba(17,35,31,.12);background:rgba(244,243,238,.88);backdrop-filter:blur(16px);position:relative;z-index:20}.inner-header{position:sticky;top:0}.brand{display:flex;align-items:center;gap:12px}.brand>span:last-child{display:flex;flex-direction:column;line-height:1.18}.brand strong{font-size:15px;letter-spacing:-.2px}.brand small{font-size:10px;color:var(--muted);letter-spacing:.1em;text-transform:uppercase;margin-top:3px}.brand-mark{width:35px;height:35px;border:1px solid var(--ink);border-radius:50%;display:flex;align-items:flex-end;justify-content:center;gap:2px;padding-bottom:9px}.brand-mark i{width:4px;background:var(--ink);border-radius:2px}.brand-mark i:nth-child(1){height:8px}.brand-mark i:nth-child(2){height:15px;background:var(--blue-dark)}.brand-mark i:nth-child(3){height:11px}.version-chip,.section-index{font-family:var(--mono);font-size:10px;letter-spacing:.08em}.version-chip{padding:7px 11px;border:1px solid var(--line);border-radius:99px;color:var(--muted)}.main-nav{display:flex;align-self:stretch;gap:36px}.main-nav a{display:flex;align-items:center;color:var(--muted);font-size:13px;font-weight:600;position:relative}.main-nav a.active{color:var(--ink)}.main-nav a.active:after{content:'';position:absolute;bottom:0;left:0;right:0;height:3px;background:var(--ink);border-radius:3px 3px 0 0}.home-link{font-size:12px;color:var(--muted);border-bottom:1px solid currentColor} +.hero{min-height:480px;display:grid;grid-template-columns:1.3fr .7fr;align-items:center;padding-block:74px 56px}.eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:.13em;font-weight:500;display:flex;align-items:center;gap:9px;margin:0 0 22px;color:#394641}.eyebrow span{display:inline-block;width:28px;height:2px;background:var(--orange)}.hero h1{font-size:clamp(43px,5vw,68px);line-height:1.08;letter-spacing:-.055em;margin:0;max-width:780px}.hero h1 em{font-style:normal;color:var(--blue-dark)}.hero-lead{color:var(--muted);font-size:16px;max-width:610px;margin:24px 0 32px}.hero-meta{display:flex;align-items:center;gap:15px;color:var(--muted);font-size:11px}.hero-meta span{display:flex;align-items:center;gap:7px}.hero-meta b{font-family:var(--mono);color:var(--ink)}.hero-meta i{height:1px;width:25px;background:var(--line)}.hero-visual{height:330px;position:relative;display:grid;place-items:center}.orbit{position:absolute;border:1px solid rgba(17,35,31,.16);border-radius:50%;transform:rotate(-19deg)}.orbit-one{width:280px;height:160px}.orbit-two{width:210px;height:300px;transform:rotate(42deg)}.visual-core{height:114px;width:114px;border-radius:50%;background:var(--ink);color:#fff;display:grid;place-items:center;position:relative;z-index:2;box-shadow:0 20px 40px rgba(17,35,31,.2)}.visual-core span{font:9px var(--mono);letter-spacing:.12em}.visual-core strong{font-size:24px;line-height:0;color:var(--lime)}.visual-node{position:absolute;background:var(--white);border:1px solid var(--line);border-radius:99px;padding:8px 13px;font:9px var(--mono);box-shadow:var(--shadow)}.node-a{left:8%;top:26%}.node-b{right:4%;top:38%;background:var(--lime)}.node-c{left:22%;bottom:10%;background:#dfe5ff} +.tool-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.tool-card{min-height:390px;padding:36px 38px;border-radius:var(--radius);position:relative;overflow:hidden;transition:transform .25s ease,box-shadow .25s ease}.tool-card:hover{transform:translateY(-5px);box-shadow:var(--shadow)}.card-blue{background:#718cfa;color:#0d1b18}.card-lime{background:var(--lime)}.tool-number{font:11px var(--mono);opacity:.65}.tool-icon{position:absolute;right:36px;top:31px;font-size:28px;width:48px;height:48px;border:1px solid rgba(17,35,31,.25);border-radius:50%;display:grid;place-items:center}.tool-kicker{font:10px var(--mono);letter-spacing:.12em;margin:63px 0 8px;opacity:.7}.tool-card h2{font-size:32px;letter-spacing:-.04em;margin:0 0 13px}.tool-card>p:not(.tool-kicker){max-width:430px;margin:0;color:rgba(17,35,31,.75);font-size:14px}.tool-card ul{list-style:none;padding:0;margin:27px 0 45px;display:flex;gap:9px;flex-wrap:wrap}.tool-card li{border:1px solid rgba(17,35,31,.18);border-radius:99px;padding:6px 10px;font-size:10px}.tool-cta{position:absolute;left:38px;bottom:33px;font-weight:700;font-size:13px}.tool-cta b{font-size:17px;margin-left:8px}.status-strip{margin-top:20px;padding:22px 26px;border:1px solid var(--line);border-radius:15px;display:flex;align-items:center;justify-content:space-between;background:rgba(255,255,255,.55)}.status-strip>div,.data-badge{display:flex;align-items:center;gap:12px}.status-strip p,.data-badge p{display:flex;flex-direction:column;margin:0}.status-strip strong,.data-badge strong{font-size:12px}.status-strip small,.data-badge small{font-size:10px;color:var(--muted)}.pulse-dot{width:9px;height:9px;border-radius:50%;background:#71ad31;box-shadow:0 0 0 5px rgba(113,173,49,.12)}.status-note{font:10px var(--mono)!important;color:var(--muted)} +.site-footer{height:90px;display:flex;align-items:center;justify-content:space-between;color:#8b9591;font:10px var(--mono);letter-spacing:.04em}.site-footer b{font-weight:400}.page-main{padding-block:45px 70px}.page-heading{display:flex;align-items:flex-end;justify-content:space-between;margin-bottom:30px}.page-heading .eyebrow{margin-bottom:11px}.page-heading h1{font-size:42px;letter-spacing:-.045em;line-height:1.12;margin:0 0 10px}.page-heading>div>p:last-child{margin:0;color:var(--muted);font-size:13px}.data-badge{border:1px solid var(--line);border-radius:12px;background:rgba(255,255,255,.55);padding:13px 17px;min-width:208px}.panel{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);box-shadow:0 9px 30px rgba(17,35,31,.035)}.workspace{display:grid}.recommendation-layout{grid-template-columns:370px 1fr;gap:20px;align-items:start}.form-panel{padding:28px;position:sticky;top:102px}.panel-title span{font:9px var(--mono);color:var(--blue-dark);letter-spacing:.1em}.panel-title h2{font-size:21px;letter-spacing:-.025em;margin:3px 0}.panel-title p{font-size:11px;color:var(--muted);margin:0}.panel-title.compact{padding:25px 26px 15px}.field-label{display:block;font-size:11px;font-weight:700;margin:22px 0 7px}.field-label b{color:#e4513e}.input-wrap{display:flex;border:1px solid var(--line);border-radius:10px;background:#fafaf7;overflow:hidden;transition:border .2s}.input-wrap:focus-within{border-color:var(--blue)}.input-prefix{display:grid;place-items:center;padding:0 11px;border-right:1px solid var(--line);font:9px var(--mono);color:var(--muted)}input,select{width:100%;height:43px;border:1px solid var(--line);border-radius:10px;background:#fafaf7;color:var(--ink);padding:0 12px;outline:none;transition:border-color .2s,box-shadow .2s}input:focus,select:focus{border-color:var(--blue);box-shadow:0 0 0 3px rgba(111,140,255,.1)}.input-wrap input{border:0;border-radius:0;box-shadow:none!important}.field-help{font-size:9px;color:#8c9692;margin:5px 0 0}.segmented{display:grid;grid-template-columns:repeat(3,1fr);gap:5px;padding:4px;border:1px solid var(--line);border-radius:10px;background:#f5f5f1}.segmented input{position:absolute;opacity:0;pointer-events:none}.segmented span{height:31px;display:grid;place-items:center;border-radius:7px;font-size:10px;cursor:pointer}.segmented input:checked+span{background:var(--white);box-shadow:0 2px 8px rgba(17,35,31,.08);font-weight:700}.primary-btn{height:44px;border:0;border-radius:10px;background:var(--ink);color:#fff;padding:0 18px;display:inline-flex;align-items:center;justify-content:center;gap:18px;font-weight:700;font-size:12px}.primary-btn:hover{background:#263a35}.full-btn{width:100%;margin-top:21px;justify-content:space-between}.full-btn b{color:var(--lime);font-size:17px}.text-btn{border:0;background:transparent;color:var(--blue-dark);font-size:10px;width:100%;padding:12px 0 4px}.form-message,.validation-line{color:#c04431;font-size:10px;min-height:16px;margin-top:8px}.form-footnote{display:flex;gap:10px;background:#f6f6f2;border-radius:10px;padding:12px;margin-top:18px}.form-footnote b{min-width:18px;height:18px;border-radius:50%;border:1px solid #9da6a2;display:grid;place-items:center;font:10px var(--mono)}.form-footnote p{font-size:9px;color:var(--muted);margin:0}.result-panel{min-height:604px;padding:29px}.result-head,.config-topline{display:flex;align-items:center}.result-head{justify-content:space-between;padding-bottom:19px;border-bottom:1px solid var(--line)}.result-head h2,.config-topline h2{font-size:21px;margin:2px 0 0;letter-spacing:-.025em}.section-index{display:block;color:var(--blue-dark)}.outline-btn{border:1px solid var(--line);border-radius:9px;background:#fff;height:36px;padding:0 13px;font-size:10px;color:var(--muted)}.outline-btn:hover{border-color:var(--ink);color:var(--ink)}.result-empty{min-height:480px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}.empty-graphic{display:flex;align-items:center;gap:8px;margin-bottom:25px}.empty-graphic span{width:54px;height:54px;border-radius:50%;border:1px solid var(--line);display:grid;place-items:center;font:9px var(--mono);background:#f8f8f5}.empty-graphic span:nth-of-type(2){background:#e5eaff}.empty-graphic span:nth-of-type(3){background:#eaf7c9}.empty-graphic i{font-style:normal;color:#a4aca9}.result-empty h3{font-size:16px;margin:0 0 7px}.result-empty p{font-size:11px;color:var(--muted);max-width:390px;margin:0}.query-summary{display:grid;grid-template-columns:1.7fr 1fr .9fr;background:#f5f5f1;border-radius:12px;margin:18px 0 13px;padding:12px 16px;gap:13px}.query-summary div{display:flex;flex-direction:column;min-width:0}.query-summary div+div{border-left:1px solid var(--line);padding-left:15px}.query-summary span{font:8px var(--mono);color:#8b9591;letter-spacing:.07em}.query-summary strong{font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px}.result-list{display:flex;flex-direction:column;gap:9px}.result-card{display:grid;grid-template-columns:37px 1fr auto;gap:14px;align-items:center;padding:15px 16px;border:1px solid var(--line);border-radius:13px;position:relative}.result-card.top-result{border-color:#98adff;background:#f7f8ff}.result-card.top-result:before{content:'BEST MATCH';position:absolute;right:13px;top:-7px;background:var(--blue);font:7px var(--mono);padding:3px 7px;border-radius:99px}.rank{font:13px var(--mono);color:#a0a9a5}.result-name{display:flex;align-items:center;gap:9px}.result-name h3{font-size:14px;margin:0}.result-name>span{font-size:8px;border:1px solid var(--line);border-radius:99px;padding:2px 6px;color:var(--muted)}.reason-tags{display:flex;gap:5px;flex-wrap:wrap;margin:6px 0 4px}.reason-tags span{font-size:8px;background:#eef1ea;padding:3px 6px;border-radius:4px}.result-main p{font-size:9px;color:var(--muted);margin:0}.score-block{display:flex;align-items:center;gap:11px}.score-ring{--score:50;width:50px;height:50px;border-radius:50%;display:grid;place-content:center;text-align:center;background:radial-gradient(circle closest-side,#fff 78%,transparent 80% 99%),conic-gradient(var(--blue-dark) calc(var(--score)*1%),#e6e9e5 0)}.score-ring strong{font:12px var(--mono);line-height:1}.score-ring small{font:7px var(--mono);color:var(--muted)}.priority{font-size:8px;border-radius:99px;padding:4px 7px;white-space:nowrap}.priority-high{background:#dfe5ff;color:#273fae}.priority-mid{background:#e9f7c5;color:#58790a}.priority-low{background:#eee;color:#6e7774}.method-note{display:flex;align-items:center;gap:8px;margin-top:14px;font-size:8px;color:var(--muted)}.method-note strong{margin-right:auto;color:var(--ink)}.method-note span{border-left:1px solid var(--line);padding-left:8px} +.generator-stack{display:flex;flex-direction:column;gap:18px}.generator-config{padding:26px}.config-topline{gap:13px}.config-topline .outline-btn{margin-left:auto}.config-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:21px}.config-grid label>span{display:block;font-size:9px;font-weight:700;margin-bottom:5px}.generator-columns{display:grid;grid-template-columns:.74fr 1.26fr;gap:18px;align-items:start}.macro-panel{overflow:hidden}.macro-search{padding:0 25px 14px}.macro-search input{height:38px}.macro-table-wrap{max-height:550px;overflow:auto;border-top:1px solid var(--line)}table{width:100%;border-collapse:collapse}.macro-table th,.macro-table td,.mapping-table th,.mapping-table td{text-align:left;border-bottom:1px solid #eceeea;padding:10px 13px;font-size:9px}.macro-table th,.mapping-table th{position:sticky;top:0;background:#f8f8f5;color:var(--muted);font:8px var(--mono);z-index:1}.macro-table th:first-child{width:42%}.macro-table code,.mapping-table code{font-family:var(--mono);font-size:9px;color:#2e48bc;word-break:break-all}.table-empty{text-align:center!important;color:var(--muted);padding:30px!important}.template-status{display:inline-block;background:#eaf7c9;color:#5b7d0a;border-radius:99px;padding:3px 7px;font-size:8px}.template-status.review{background:#ffecdf;color:#b25329}.output-panel{padding:26px}.output-title{padding-bottom:16px;border-bottom:1px solid var(--line)}.live-chip{font:8px var(--mono);margin-left:auto;color:#4f7320;display:flex;align-items:center;gap:5px}.live-chip i{width:6px;height:6px;border-radius:50%;background:#7ab836}.mapping-table-wrap{max-height:315px;overflow:auto;margin-top:12px;border:1px solid var(--line);border-radius:10px}.mapping-table th:first-child{width:34%}.mapping-table td{padding:6px 10px}.mapping-table input{height:30px;border:0;background:transparent;padding:0;font:9px var(--mono);box-shadow:none!important}.output-label{display:flex;justify-content:space-between;align-items:center;margin:17px 0 7px;font-size:10px;font-weight:700}.output-label small{font:8px var(--mono);color:var(--muted);font-weight:400}.url-output{min-height:128px;max-height:210px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;margin:0;background:var(--ink);color:#dff28d;border-radius:12px;padding:15px;font:10px/1.7 var(--mono);border:1px solid #263b35}.output-actions{display:flex;align-items:center;gap:12px;margin-top:12px}.copy-status{font-size:9px;color:#4d7622}.toast{position:fixed;left:50%;bottom:30px;transform:translate(-50%,20px);opacity:0;pointer-events:none;background:var(--ink);color:#fff;padding:10px 16px;border-radius:99px;font-size:10px;transition:.25s;z-index:100}.toast.show{opacity:1;transform:translate(-50%,0)} +@media(max-width:900px){.hero{grid-template-columns:1fr}.hero-visual{display:none}.recommendation-layout,.generator-columns{grid-template-columns:1fr}.form-panel{position:static}.config-grid{grid-template-columns:repeat(2,1fr)}.main-nav{gap:18px}.method-note{flex-wrap:wrap}.method-note strong{width:100%}} +@media(max-width:620px){.shell{width:min(100% - 28px,1180px)}.site-header{height:68px;padding-inline:14px}.brand small,.home-link,.version-chip{display:none}.main-nav{gap:13px}.main-nav a{font-size:11px}.hero{min-height:auto;padding-block:55px 45px}.hero h1{font-size:39px}.hero-meta{display:none}.tool-grid{grid-template-columns:1fr}.tool-card{min-height:365px;padding:28px}.tool-cta{left:28px}.status-strip,.page-heading{align-items:flex-start;gap:17px;flex-direction:column}.status-note{display:none}.page-main{padding-block:32px 50px}.page-heading h1{font-size:34px}.data-badge{width:100%}.recommendation-layout{gap:14px}.form-panel,.result-panel,.generator-config,.output-panel{padding:20px}.result-card{grid-template-columns:30px 1fr}.score-block{grid-column:2;justify-content:flex-start}.query-summary{grid-template-columns:1fr}.query-summary div+div{border-left:0;padding-left:0;border-top:1px solid var(--line);padding-top:8px}.method-note{display:none}.config-grid{grid-template-columns:1fr}.generator-columns{gap:14px}.site-footer{height:70px}.site-footer span:first-child{display:none}} diff --git a/channel-recommendation.html b/channel-recommendation.html new file mode 100644 index 0000000..f92b96d --- /dev/null +++ b/channel-recommendation.html @@ -0,0 +1,74 @@ + + + + + + + 渠道投放建议 · Traffic Intelligence + + + + + +
+
+

CHANNEL ADVISOR / 01

渠道投放建议

通过产品信息快速筛选候选渠道,并展示每个排序结果的匹配依据。

+

规则基线 v0.1正式绩效数据待接入

+
+ +
+ + +
+
+
OUTPUT

优先渠道

+ +
+
+
PKG+CAT+GEO
+

等待输入产品信息

完成左侧三个必填字段后,这里会显示候选渠道、优先级和详细匹配原因。

+
+ +
+
+
+ + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..83692c3 --- /dev/null +++ b/index.html @@ -0,0 +1,66 @@ + + + + + + + Traffic Intelligence Hub + + + + + +
+
+
+

MEDIA OPERATIONS TOOLKIT

+

从渠道判断到链接生成,
让投放准备更简单。

+

一个面向投放团队的轻量工作台。先快速定位候选渠道,再按媒体宏规则生成可用的 Tracking Link。

+
+ 01 渠道建议02 链接生成03 数据规则持续迭代 +
+
+ +
+ +
+ +
01
+ +

CHANNEL ADVISOR

+

渠道投放建议

+

输入包名、产品品类与投放国家,获取按优先级排列的渠道候选及匹配理由。

+
  • 可解释的评分结构
  • 品类与 GEO 双重匹配
  • 预留真实绩效数据接口
+ 开始匹配 → +
+ +
02
+ +

TRACKING BUILDER

+

自投链接生成器

+

选择自投媒体,填写业务参数,按平台专属宏规则实时生成 Click / Impression 链接。

+
  • 平台宏模板集中管理
  • 业务参数实时替换
  • 一键复制最终链接
+ 生成链接 → +
+
+ +
+

当前阶段交互框架已就绪,等待接入正式规则与数据

+

静态页面 · 无需构建 · 支持 AgentStage 直接发布

+
+
+ + + + + diff --git a/link-generator.html b/link-generator.html new file mode 100644 index 0000000..732ef61 --- /dev/null +++ b/link-generator.html @@ -0,0 +1,64 @@ + + + + + + + 自投链接生成器 · Traffic Intelligence + + + + + +
+
+

TRACKING BUILDER / 02

自投平台链接生成器

选择媒体模板,填写订单参数,并实时检查平台宏映射与最终链接。

+

— 个平台模板Click / Impression

+
+ +
+
+
STEP 01

选择模板与业务参数

+
+ + + + + + + + + +
+ +
+ +
+
+
STEP 02

媒体宏参考

+ +
媒体宏说明
+
+ +
+
STEP 03

参数映射与输出

LIVE
+
参数 Key媒体 Value / Macro
+
最终投放链接0 chars
+

+          
+
+
+
+
+ +
+ + + + + +