{"id":"52ebf74a-c47e-4d6f-b5cc-cdb056d9c80f","name":"Top Ten Referrers","slug":"top-ten-referrers","category":"email-charts","description":"A ranked horizontal top-10 bar chart for traffic digest emails: pass any number of name:value pairs, it sorts them, keeps the top nine and folds the remainder into a gray tenth bar. Value labels included.","sample_params":{"eyebrow":"Traffic digest","footnote":"Aug 4 – Aug 10","hue":"210","items":"Google:4210,Direct:2360,X / Twitter:1890,LinkedIn:1240,GitHub:980,Product Hunt:720,Hacker News:540,Reddit:410,Bing:280,Newsletter:170,Facebook:120","subtitle":"Referrers · last 7 days","title":"Where your visitors came from"},"spec":{"name":"top-ten-referrers","width":1200,"height":630,"scale":2,"html":"\u003c!doctype html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n\u003cmeta charset='utf-8'\u003e\n\u003cstyle\u003e\n*{margin:0;padding:0;box-sizing:border-box}\nhtml,body{width:100%;height:100%}\nbody{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;overflow:hidden}\n.eyebrow{font-size:20px;font-weight:700;letter-spacing:.16em;text-transform:uppercase}\n.chip{display:inline-block;font-size:22px;font-weight:700;padding:6px 18px;border-radius:999px;vertical-align:middle}\n.chip.up{color:#0a7d4f;background:#e2f5ea}\n.chip.down{color:#b3261e;background:#fde9e7}\n.chip.flat{color:#5b6472;background:#eef0f4}\n\nbody{background:#fff;color:#12161f}\n.card{width:100vw;height:100vh;padding:52px 64px 42px;display:flex;flex-direction:column}\n.eyebrow{color:hsl(var(--h) 70% 46%)}\nh1{font-size:46px;font-weight:800;letter-spacing:-0.02em;margin-top:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.subtitle{margin-top:6px;font-size:23px;color:#79818f}\n.chartbox{flex:1;min-height:0;margin-top:20px}\nh1,.eyebrow,.subtitle,.foot{flex:none}\n.foot{margin-top:12px;display:flex;justify-content:space-between;font-size:18px;color:#98a0af;letter-spacing:.06em;text-transform:uppercase}\n\u003c/style\u003e\n\u003c/head\u003e\n\u003cbody style='--h: {{.hue}}'\u003e\n\u003cdiv class='card'\u003e\n  \u003cp class='eyebrow'\u003e{{.eyebrow}}\u003c/p\u003e\n  \u003ch1\u003e{{.title}}\u003c/h1\u003e\n  {{if .subtitle}}\u003cp class='subtitle'\u003e{{.subtitle}}\u003c/p\u003e{{end}}\n  \u003cdiv class='chartbox'\u003e\u003ccanvas id='c' width='1072' height='340'\u003e\u003c/canvas\u003e\u003c/div\u003e\n  \u003cdiv class='foot'\u003e\u003cspan\u003emedia0\u003c/span\u003e\u003cspan\u003e{{.footnote}}\u003c/span\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003cscript src='https://cdn.jsdelivr.net/npm/chart.js@4.4.9/dist/chart.umd.js'\u003e\u003c/script\u003e\n\u003cscript\u003e\nvar HUE=Number({{.hue}});\nvar REST={{.rest_label}};\nvar items={{.items}}.split(',').map(function(s){\n  var i=s.lastIndexOf(':');\n  return {name:s.slice(0,i).trim(),value:Number(s.slice(i+1))};\n}).filter(function(d){return d.name\u0026\u0026isFinite(d.value)});\nitems.sort(function(a,b){return b.value-a.value});\nif(items.length\u003e10){\n  var rest=items.slice(9).reduce(function(a,d){return a+d.value},0);\n  items=items.slice(0,9);\n  items.push({name:REST,value:rest});\n}\nvar names=items.map(function(d){return d.name});\nvar values=items.map(function(d){return d.value});\nvar valueLabels={\n  id:'valueLabels',\n  afterDatasetsDraw:function(chart){\n    var ctx=chart.ctx,meta=chart.getDatasetMeta(0);\n    ctx.save();\n    ctx.font=\"700 21px -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif\";\n    ctx.fillStyle='#47506b';\n    ctx.textBaseline='middle';\n    meta.data.forEach(function(bar,i){\n      ctx.fillText(values[i].toLocaleString('en-US'),bar.x+10,bar.y);\n    });\n    ctx.restore();\n  }\n};\nChart.defaults.font.family=\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif\";\nChart.defaults.color='#5b6472';\nnew Chart(document.getElementById('c'),{\n  type:'bar',\n  plugins:[valueLabels],\n  data:{labels:names,datasets:[{\n    data:values,\n    backgroundColor:items.map(function(d){return d.name===REST?'#ccd2dc':'hsl('+HUE+' 74% 52%)'}),\n    borderRadius:7,borderSkipped:false,maxBarThickness:26,categoryPercentage:.78\n  }]},\n  options:{\n    indexAxis:'y',responsive:false,animation:false,devicePixelRatio:window.devicePixelRatio,\n    layout:{padding:{right:110}},\n    plugins:{legend:{display:false},tooltip:{enabled:false}},\n    scales:{\n      x:{beginAtZero:true,grid:{color:'#eef0f4'},border:{display:false},ticks:{maxTicksLimit:6,font:{size:19}}},\n      y:{grid:{display:false},border:{display:false},ticks:{autoSkip:false,font:{size:22,weight:600},callback:function(v,i){\n        var s=(i+1)+'.  '+names[i];return s.length\u003e30?s.slice(0,29)+'\\u2026':s;\n      }}}\n    }\n  }\n});\n\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n","params":{"eyebrow":{"type":"string","default":"Traffic digest","maxLen":40,"description":"Small uppercase kicker above the title."},"footnote":{"type":"string","maxLen":60,"description":"Small right-aligned footer note."},"hue":{"type":"number","default":"210","maxLen":5,"description":"Accent hue 0-360 for the ranked bars."},"items":{"type":"string","required":true,"maxLen":1500,"description":"Comma-separated name:value pairs in any order, e.g. Google:4210,Direct:2360. Sorted descending; beyond 9 entries the rest is folded into one final bar."},"rest_label":{"type":"string","default":"Everything else","maxLen":30,"description":"Label of the folded remainder bar."},"subtitle":{"type":"string","maxLen":90,"description":"Supporting line under the title."},"title":{"type":"string","required":true,"maxLen":70,"description":"Chart headline."}}}}
