PageSourceSearch

https://lysin-dx-project.onrender.com/assets/AdPerformancePage-Dt1bGGHC.js

js lysin-dx-project.onrender.com collected 2026-10-03 11:41:41 UTC 16,909 bytes, 1 lines download raw bytes

1import{j as t,L as G,g as ie,u as ce,e as de}from"./index-CmawXwhp.js";import{a0 as d,k as J,D as ee,U as te,Q as se,r as re}from"./vendor-icons-CmtbFRhB.js";import{P as ae}from"./PageHeader-B_xdAc5E.js";import{C as w}from"./Card-DE-byskL.js";import{S}from"./StatCard-DkK21lWb.js";import{L as oe}from"./LoadErrorCard-D9EmSEbm.js";import{D as W}from"./DataProvider-D8exVQeK.js";import{m as T,y as N,n as $,f as Y,r as ue,u as pe,M as me}from"./format-DnClS-0s.js";import"./vendor-charts-DvBYz3sx.js";import"./Badge-Cvwwqv1A.js";function fe({ja:e}){const[u,k]=d.useState(null),[R,p]=d.useState(!0),[a,E]=d.useState(null),[f,F]=d.useState("cost"),[C,_]=d.useState("desc"),[g,M]=d.useState("");if(d.useEffect(()=>{p(!0),W.getActiveProvider().getAmazonAdPerformance(u||void 0).then(r=>{E(r),p(!1)}).catch(r=>{console.error("Failed to load Amazon ad performance:",r),p(!1)})},[u]),R)return t.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"250px",color:"var(--lysin-text-muted)",fontFamily:"monospace"},children:[t.jsx(J,{size:16,style:{marginRight:8,animation:"spin 2s linear infinite"}})," Loading…"]});if(a!=null&&a.load_error)return t.jsx(oe,{});const y=(a==null?void 0:a.rows)||[];if(!y.length)return t.jsx(w,{title:e?"Amazon データ未取込":"No Amazon data ingested yet",children:t.jsxs("div",{style:{fontSize:14,color:"var(--lysin-text-muted)",lineHeight:1.7},children:[e?"Amazon Ads API からの取込がまだありません。日次の自動取込が始まるとここに商品別の広告効率が表示されます。":"Nothing has been ingested from the Amazon Ads API yet. Once the daily import runs, per-SKU ad efficiency appears here.",t.jsxs("div",{style:{marginTop:8},children:[e?"最終取込":"Last ingest",": ",(a==null?void 0:a.last_ingested_at)||"—"]})]})});const l=[...g?y.filter(r=>String(r.sku||"").toLowerCase().includes(g.toLowerCase())):y].sort((r,i)=>{const c=r[f]==null?-1/0:Number(r[f]),U=i[f]==null?-1/0:Number(i[f]);return C==="desc"?U-c:c-U}),b=y.filter(r=>r.roas!=null&&r.cost>0),v=[...b].sort((r,i)=>i.roas-r.roas)[0],h=[...b].sort((r,i)=>r.roas-i.roas)[0],m=a.totals||{},j=[{key:"sku",label:"SKU",sortable:!1},{key:"cost",label:e?"広告費":"Spend",fmt:N,bold:!0},{key:"impressions",label:e?"表示回数":"Impr.",fmt:$},{key:"clicks",label:e?"クリック":"Clicks",fmt:$},{key:"ctr",label:"CTR",fmt:Y},{key:"cpc",label:"CPC",fmt:N},{key:"purchases_7d",label:e?"注文(7日)":"Orders (7d)",fmt:$},{key:"sales_7d",label:e?"売上(7日)":"Sales (7d)",fmt:N},{key:"roas",label:"ROAS",fmt:T,color:!0},{key:"acos",label:"ACOS",fmt:Y}],O=r=>{const i=f===r.key;return t.jsxs("th",{onClick:r.sortable===!1?void 0:()=>{i?_(c=>c==="desc"?"asc":"desc"):(F(r.key),_("desc"))},style:{textAlign:r.key==="sku"?"left":"right",padding:"var(--space-2) var(--space-3)",fontSize:"11px",fontWeight:700,letterSpacing:".04em",whiteSpace:"nowrap",color:i?"var(--lysin-accent)":"var(--lysin-text-muted)",cursor:r.sortable===!1?"default":"pointer",borderBottom:"1px solid var(--lysin-border)"},children:[r.label,i?C==="desc"?" ↓":" ↑":""]},r.key)};return t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"var(--space-6)"},"data-testid":"amazon-ad-performance",children:[(a.available_months||[]).length>1&&t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)",flexWrap:"wrap"},children:[t.jsx("span",{style:{fontSize:"11px",fontWeight:700,letterSpacing:".04em",color:"var(--lysin-text-muted)"},children:e?"対象月":"Month"}),a.available_months.map(r=>{const i=r===a.month;return t.jsx("button",{type:"button",onClick:()=>k(r),style:{minHeight:"32px",padding:"0 var(--space-3)",fontSize:"12px",fontWeight:600,cursor:"pointer",borderRadius:"16px",border:i?"1px solid var(--lysin-accent)":"1px solid var(--lysin-border)",backgroundColor:i?"var(--lysin-accent)":"var(--lysin-surface)",color:i?"#fff":"var(--lysin-text)"},children:r},r)})]}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(200px, 1fr))",gap:"var(--space-4)"},children:[t.jsx(S,{title:e?"広告費合計":"Total Ad Spend",value:N(m.cost),icon:ee,description:`${y.length} ${e?"商品":"SKUs"} · ROAS ${T(m.roas)}`}),t.jsx(S,{title:e?"最高ROAS商品":"Best ROAS SKU",value:v?T(v.roas):"—",icon:te,de
1scription:v?v.sku:""}),t.jsx(S,{title:e?"最低ROAS商品(要確認)":"Worst ROAS SKU",value:h?T(h.roas):"—",icon:se,description:h?h.sku:""}),t.jsx(S,{title:e?"総クリック":"Total Clicks",value:$(m.clicks),icon:re})]}),t.jsxs(w,{title:e?"商品別 Amazon 広告パフォーマンス(列見出しクリックで並替)":"Per-SKU Amazon Ad Performance (click a header to sort)",subtitle:e?`Amazon スポンサープロダクト広告 · ${a.month}。売上・注文は広告クリック後7日以内の帰属分(Amazon の仕様)なので、楽天の ROAS とは直接比較できません。直近の日は帰属確定まで毎日更新されます。最終取込: ${a.last_ingested_at||"—"}`:`Amazon Sponsored Products · ${a.month}. Sales and orders are attributed within 7 days of an ad click, so ROAS is not comparable with Rakuten's. Recent days are restated daily until attribution closes. Last ingest: ${a.last_ingested_at||"—"}`,children:[t.jsx("input",{type:"text",value:g,onChange:r=>M(r.target.value),placeholder:e?"SKUで絞り込み...":"Filter by SKU...",style:{width:"240px",maxWidth:"100%",padding:"var(--space-2) var(--space-3)",fontSize:"13px",backgroundColor:"var(--lysin-surface)",border:"1px solid var(--lysin-border)",borderRadius:"var(--radius-sm)",color:"var(--lysin-text)",outline:"none",boxSizing:"border-box"}}),t.jsx("div",{className:"lysin-table-scroll",style:{minWidth:0,maxWidth:"100%",contain:"inline-size"},children:t.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontVariantNumeric:"tabular-nums"},children:[t.jsx("thead",{children:t.jsx("tr",{children:j.map(O)})}),t.jsx("tbody",{children:l.map((r,i)=>t.jsx("tr",{style:{borderBottom:"1px solid var(--lysin-border)"},children:j.map(c=>t.jsx("td",{style:{textAlign:c.key==="sku"?"left":"right",padding:"var(--space-2) var(--space-3)",fontSize:13,whiteSpace:"nowrap",fontFamily:c.key==="sku"?"monospace":void 0,color:c.color?ue(r.roas):"var(--lysin-text)",fontWeight:c.bold||c.color?700:400},children:c.key==="sku"?r.sku?t.jsx(G,{to:`/inventory/sku-records?q=${encodeURIComponent(r.sku)}`,style:{color:"var(--lysin-accent)",textDecoration:"underline",textUnderlineOffset:"3px"},children:r.sku}):t.jsx("span",{style:{color:"var(--lysin-text-muted)"},children:e?"(SKUなし)":"(no SKU)"}):c.fmt(r[c.key])},c.key))},`${r.sku}-${i}`))})]})})]})]})}const ye=new Set(["uu","revenue","page_roas"]),he=e=>e==null?"—":`¥${Math.round(Number(e)).toLocaleString()}`,A=e=>e==null?"—":`¥${Number(e).toLocaleString()}`,D=e=>e==null?"—":`${(Number(e)/100).toFixed(2)}x`,Z=e=>e==null?"—":`${Number(e).toFixed(2)}%`,L=e=>e==null?"—":Number(e).toLocaleString();function xe(e){if(e==null)return"var(--lysin-text-muted)";const u=Number(e)/100;return u>=3?"var(--lysin-ok)":u>=1?"var(--lysin-warn)":"var(--lysin-danger)"}function we(){const{lang:e}=ie(),u=e==="ja";ce(u?"商品別広告効率 | SyncBridge":"Per-SKU Ad Efficiency | SyncBridge",u?"楽天(RPP・CA)と Amazon 広告の商品別ROAS/CPC/CTR。予算配分の意思決定用。":"Per-SKU Rakuten (RPP/CA) and Amazon ad ROAS, CPC, CTR for budget decisions.");const[k,R]=pe(),p=t.jsx(me,{mall:k,onChange:R});return k!=="AMAZON"?t.jsx(ve,{lang:e,mallSwitch:p}):t.jsxs(t.Fragment,{children:[t.jsx(ae,{title:u?"商品別広告効率 / Ad Efficiency":"Per-SKU Ad Efficiency",statusText:u?"Amazon スポンサープロダクト広告":"Amazon Sponsored Products"}),p,t.jsx(fe,{ja:u})]})}function ve({lang:e,mallSwitch:u}){var H,V,X,q;const[k]=de(),[R,p]=d.useState(!0),[a,E]=d.useState(null),[f,F]=d.useState("total_spend"),[C,_]=d.useState("desc"),[g,M]=d.useState(null),[y,I]=d.useState(k.get("sku")||""),[l,b]=d.useState(null),[v,h]=d.useState(!1);d.useEffect(()=>{p(!0),W.getActiveProvider().getAdPerformance(g||void 0).then(s=>{E(s),p(!1)}).catch(s=>{console.error("Failed to load ad performance:",s),p(!1)})},[g]);const m=(a==null?void 0:a.year_month)||null;d.useEffect(()=>{if(!m){b(null),h(!1);return}let s=!0;return W.getActiveProvider().getSkuPerformance(m,"3",!0).then(o=>{if(!s)return;if(o!=null&&o.load_error){b(null),h(!0);return}const n={};
1(o.rows||[]).forEach(x=>{n[x.sku]=x}),b({by:n,envelope:o}),h(!1)}).catch(()=>{s&&(b(null),h(!0))}),()=>{s=!1}},[m]);const j=a&&a.rows||[],O=j.length>0,r=y?j.filter(s=>String(s.sku||"").toLowerCase().includes(y.toLowerCase())):j,i=(l==null?void 0:l.by)||{},c=(s,o)=>{var n;return ye.has(o)?(n=i[s.sku])==null?void 0:n[o]:s[o]},U=[...r].sort((s,o)=>{const n=c(s,f),x=c(o,f),P=n==null?-1/0:Number(n),Q=x==null?-1/0:Number(x);return C==="desc"?Q-P:P-Q}),ne=r.reduce((s,o)=>s+Number(o.total_spend||0),0),z=r.filter(s=>s.rpp_roas!=null).sort((s,o)=>Number(o.rpp_roas)-Number(s.rpp_roas))[0],K=r.filter(s=>s.rpp_roas!=null&&Number(s.rpp_spend)>0).sort((s,o)=>Number(s.rpp_roas)-Number(o.rpp_roas))[0],B=[{key:"sku",label:"SKU",sortable:!1},{key:"rpp_spend",label:e==="ja"?"RPP広告費":"RPP Spend",fmt:A},{key:"rpp_clicks",label:e==="ja"?"クリック":"Clicks",fmt:L},{key:"rpp_ctr",label:"CTR",fmt:Z},{key:"rpp_cpc",label:"CPC",fmt:A},{key:"rpp_roas",label:"ROAS",fmt:D,color:!0},{key:"rpp_cvr",label:"CVR",fmt:Z},{key:"rpp_sales_count",label:e==="ja"?"売上件数":"Orders",fmt:L},{key:"rpp_cpa",label:e==="ja"?"注文獲得単価":"CPA",fmt:A},{key:"ca_spend",label:e==="ja"?"CA広告費":"CA Spend",fmt:A},{key:"total_spend",label:e==="ja"?"合計広告費":"Total Spend",fmt:A},{key:"uu",label:e==="ja"?"アクセス":"UU",fmt:L,x:!0},{key:"revenue",label:e==="ja"?"売上(推定)":"Revenue (est.)",fmt:he,x:!0,est:!0},{key:"page_roas",label:e==="ja"?"ページROAS(推定)":"Page ROAS (est.)",fmt:s=>s==null?"—":`${Number(s).toFixed(2)}x`,x:!0,est:!0}],le=s=>{const o=f===s.key;return t.jsxs("th",{onClick:s.sortable===!1?void 0:()=>{o?_(n=>n==="desc"?"asc":"desc"):(F(s.key),_("desc"))},style:{textAlign:s.key==="sku"?"left":"right",padding:"var(--space-2) var(--space-3)",fontSize:"11px",fontWeight:700,textTransform:"uppercase",letterSpacing:".04em",color:o?"var(--lysin-accent)":"var(--lysin-text-muted)",cursor:s.sortable===!1?"default":"pointer",whiteSpace:"nowrap",borderBottom:"1px solid var(--lysin-border)"},children:[s.label,o?C==="desc"?" ↓":" ↑":""]},s.key)};return t.jsxs(t.Fragment,{children:[t.jsx(ae,{title:e==="ja"?"商品別広告効率 / Ad Efficiency":"Per-SKU Ad Efficiency",statusText:O?e==="ja"?`対象月: ${a.month}`:`Month: ${a.month}`:void 0,helpLink:"/sales/rms-fetch"}),u,R?t.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"250px",color:"var(--lysin-text-muted)",fontFamily:"monospace"},children:[t.jsx(J,{size:16,style:{marginRight:8,animation:"spin 2s linear infinite"}})," Loading…"]}):a!=null&&a.load_error?t.jsx(oe,{}):O?t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"var(--space-6)"},children:[(!m||v||((H=l==null?void 0:l.envelope)==null?void 0:H.unplaced_ad_rows)>0||((V=l==null?void 0:l.envelope)==null?void 0:V.uu_is_partial))&&t.jsx(w,{accent:v||!m?"warn":void 0,title:e==="ja"?"アクセス・売上列について":"About the access / revenue columns",children:t.jsxs("div",{style:{fontSize:13,color:"var(--lysin-text-muted)",lineHeight:1.8},children:[!m&&t.jsx("div",{children:e==="ja"?"⚠ この月は年が記録されていないため、アクセス・売上・ページROAS は結合できません(推測はしません)。次回のRPP/CA取込で解消します。":"⚠ This month has no recorded year, so access / revenue / page ROAS cannot be joined (we do not guess). The next RPP/CA upload resolves it."}),v&&t.jsx("div",{children:e==="ja"?"⚠ アクセス・売上データの取得に失敗しました。左側の広告数値は正常です。":"⚠ Could not load the access / revenue data. The ad figures on the left are unaffected."}),((X=l==null?void 0:l.envelope)==null?void 0:X.unplaced_ad_rows)>0&&t.jsx("div",{children:e==="ja"?`※ 年が未記録の広告行が ${l.envelope.unplaced_ad_rows} 件あり、どの月にも含めていません。`:`${l.envelope.unplaced_ad_rows} ad rows have no recorded period and are excluded from every month.`}),((q=l==null?void 0:l.envelope)==null?void 0:q.uu_is_partial)&&t.jsx("div",{children:e==="ja"?"※ 対象月は進行中です。アクセス・売上は月末までの途中経過です。":"This month is still in progress — access and revenue are partial."}),t.jsx("div",{style:{marginTop:"var(--space-2)"},children:e==="ja"?"売上・ページROAS は注文実績から按分した推定値です(広告費・アクセスは実測値)。":"Revenue and page ROAS are ESTIMATES allocated from real orders; ad spend and access are measured."})]})}),(a.available_months||[]).length>1&&t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)",flexWrap:"wrap"},children:[t.jsx("span",{style:{fontSize:"11px",fontWeight:700,textTransform:"uppercase",letterSpacing:".04em",color:"var(--lysin-text-muted)"}
1,children:e==="ja"?"対象月":"Month"}),a.available_months.map(s=>{const o=s===a.month;return t.jsx("button",{onClick:()=>M(s),style:{minHeight:"32px",padding:"0 var(--space-3)",fontSize:"12px",fontWeight:600,cursor:"pointer",borderRadius:"16px",border:o?"1px solid var(--lysin-accent)":"1px solid var(--lysin-border)",backgroundColor:o?"var(--lysin-accent)":"var(--lysin-surface)",color:o?"#fff":"var(--lysin-text)"},children:s},s)})]}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(220px, 1fr))",gap:"var(--space-4)"},children:[t.jsx(S,{title:e==="ja"?"広告費合計":"Total Ad Spend",value:A(ne),icon:ee,description:`${r.length} ${e==="ja"?"商品":"SKUs"}`}),t.jsx(S,{title:e==="ja"?"最高ROAS商品":"Best ROAS SKU",value:z?D(z.rpp_roas):"—",icon:te,description:z?z.sku:""}),t.jsx(S,{title:e==="ja"?"最低ROAS商品(要確認)":"Worst ROAS SKU",value:K?D(K.rpp_roas):"—",icon:se,description:K?K.sku:""}),t.jsx(S,{title:e==="ja"?"総クリック":"Total Clicks",value:L(r.reduce((s,o)=>s+Number(o.rpp_clicks||0),0)),icon:re})]}),t.jsxs(w,{title:e==="ja"?"商品別 広告パフォーマンス(列見出しクリックで並替)":"Per-SKU Ad Performance (click a header to sort)",subtitle:e==="ja"?"ROASは楽天レポートの%を倍率表示(720時間帰属)。売上系(売上件数・注文獲得単価・CVR・ROAS)は月末+30日の帰属確定まで暫定値。ROAS<1xは広告が赤字の可能性。SKUクリックでSKU台帳へ。":"ROAS shown as a return multiple from the RMS % (720h attribution). Sales-side figures (orders, CPA, CVR, ROAS) stay provisional until month-end + 30 days. ROAS < 1x = ads likely losing money. Click a SKU for its ledger entry.",children:[t.jsx("input",{type:"text",value:y,onChange:s=>I(s.target.value),placeholder:e==="ja"?"SKUで絞り込み...":"Filter by SKU...",style:{width:"240px",maxWidth:"100%",margin:"var(--space-2) 0",padding:"var(--space-2) var(--space-3)",fontSize:"13px",backgroundColor:"var(--lysin-surface)",border:"1px solid var(--lysin-border)",borderRadius:"var(--radius-sm)",color:"var(--lysin-text)",outline:"none",boxSizing:"border-box"}}),t.jsx("div",{className:"lysin-table-scroll",style:{marginTop:"var(--space-2)"},children:t.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontVariantNumeric:"tabular-nums"},children:[t.jsx("thead",{children:t.jsx("tr",{children:B.map(le)})}),t.jsx("tbody",{children:U.map((s,o)=>t.jsx("tr",{style:{borderBottom:"1px solid var(--lysin-border)"},children:B.map(n=>t.jsx("td",{style:{textAlign:n.key==="sku"?"left":"right",padding:"var(--space-2) var(--space-3)",fontSize:13,fontFamily:n.key==="sku"?"monospace":void 0,color:n.color?xe(s[n.key]):n.key==="sku"?"var(--lysin-accent)":"var(--lysin-text)",fontWeight:n.key==="total_spend"||n.color?700:400,whiteSpace:"nowrap"},children:n.key==="sku"?t.jsx(G,{to:`/inventory/sku-records?q=${encodeURIComponent(s.sku)}`,title:e==="ja"?"SKU台帳で開く":"Open in SKU Records",style:{color:"var(--lysin-accent)",textDecoration:"underline",textUnderlineOffset:"3px"},children:s.sku}):(()=>{var P;const x=n.x?(P=i[s.sku])==null?void 0:P[n.key]:s[n.key];return n.x&&x==null?"—":n.fmt?n.fmt(x):x})()},n.key))},s.sku+o))})]})})]})]}):t.jsx(w,{title:e==="ja"?"データがありません":"No data yet",children:t.jsx("div",{style:{fontSize:14,color:"var(--lysin-text-muted)",lineHeight:1.7},children:e==="ja"?"RPP / CA のレポートを「RMS取得パネル」から取り込むと、商品別の広告効率がここに表示されます。":"Ingest the RPP / CA reports via the RMS Fetch Panel and per-SKU ad efficiency appears here."})})]})}export{we as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.