Web Challenge 2026 — Multi-Channel Marketing Dashboard

Thanks for participating!

Build a multi-channel marketing dashboard that visualizes ad performance data across four platforms: Facebook, Google, Instagram, and LinkedIn. Two API endpoints are available — your job is to consume them, make the data legible, and give users the tools to act on it.

This is intentionally open-ended. The requirements below define the floor — how far above it you go is up to you.

Questions welcome. If anything here is unclear, ask. We'd rather clarify upfront than have you build in the wrong direction.

What You Must Build

  1. Dashboard page. A single overview page with summary widgets for all supported platforms. Each widget should give the user a quick read on key performance indicators and link through to the appropriate detail page. Use GET /v1/metrics-summary for this page (fixed 30-day rolling window, no date parameters needed).
  2. One page per network. Detail pages for Meta (Facebook + Instagram), Google, and LinkedIn. These pages should go deeper than the dashboard — surface platform-specific metrics, show trends over time, and make the data explorable.
  3. Charts. Each network page must include at least one chart visualizing data over time. If you include multiple charts, decide the best way to present them (tabs, toggle, layered, etc.).
  4. Date range and comparison. The detail pages must include a date range picker. Default: 14 days. Minimum: 7 days. Maximum: 30 days. The comparison period (equal-length window immediately before the selected range) is computed automatically by the backend — no second date picker needed. Show a delta on each metric indicating whether the change is favorable or unfavorable.
  5. CSV export. Users must be able to export the relevant data as a CSV file. The export should reflect the current view and include enough context to be useful on its own.
  6. Navigation. Users must be able to move between the dashboard and each network page without a full page reload. Use react-router-dom for client-side routing.
  7. Loading and error states. Every data fetch must have a visible loading state and a visible error state. The user should never see a blank screen with no explanation.
  8. Custom hooks. Data fetching logic must live in custom hooks, not inline in components. Components should stay focused on rendering; data logic should be reusable and independently testable.

Tech Stack

The following are required:

LayerRequirement
LanguageTypeScript
FrameworkReact
Stylingstyled-components
Routingreact-router-dom
ChartsA chart library — we suggest react-google-charts, but any equivalent is fine
CSV exportA CSV parser library (e.g. papaparse) — don't hand-roll string concatenation

Everything else is your call. If you want to add a state management library, a component library, or additional utilities, go for it — just be ready to explain why.

API Reference

Base URL: https://eulerity-hackathon.appspot.com
The Vite dev server proxies /v1/* to this base URL, so during local development you can call endpoints with relative paths (e.g. /v1/metrics-summary).

GET /v1/metrics-summary

Returns all four platforms in a single payload for the dashboard overview. The window is always today minus 29 days (current) and the 30 days before that (previous). No parameters — the backend computes everything.

Sample: https://eulerity-hackathon.appspot.com/v1/metrics-summary

GET /v1/metrics-insights?network=<name>&startDate=<date>&endDate=<date>

Returns full daily metrics for a single network, including rate fields and platform-specific engagement. Use this for per-network detail pages.

ParameterRequiredValues
networkYesmeta | google | linkedin
startDateYesISO date, e.g. 2026-05-27
endDateYesISO date, e.g. 2026-06-09

Validation: The window must be 7–30 days inclusive. The comparison period (equal-length window immediately before startDate) is returned automatically as previousPeriod — no second request needed.

Note on rate fields: ctr, cpc, cpm, and costPerConversion in totals and previousTotals are recalculated from summed base values, not averaged from daily rates.

Error Responses

All errors return { "error": "ERROR_CODE", "message": "..." }.

StatusCodeWhen it occurs
400MISSING_PARAMA required parameter is absent
400INVALID_NETWORKnetwork is not meta, google, or linkedin
400INVALID_DATE_FORMATA date is not in YYYY-MM-DD format
400INVALID_DATE_RANGEendDate is before startDate
400WINDOW_TOO_SMALLRange is fewer than 7 days
400WINDOW_TOO_LARGERange exceeds 30 days
404NOT_FOUNDPath does not match either endpoint
405METHOD_NOT_ALLOWEDNon-GET request on either endpoint

Data Types

SummaryMetrics (summary endpoint only): date, impressions, clicks, spend (USD), conversions.

DailyMetrics (base for all insights): extends SummaryMetrics with ctr (%), cpc (USD), cpm (USD per 1k impressions).

FacebookDailyMetrics: extends DailyMetrics with reach, likes, comments, shares.

InstagramDailyMetrics: extends DailyMetrics with reach, likes, comments, saves.

GoogleDailyMetrics: extends DailyMetrics with costPerConversion (USD; zero when no conversions).

LinkedInDailyMetrics: extends DailyMetrics with likes, comments, shares, follows.

Data Characteristics

The data is synthetically generated on every request — there is no database. Values follow a slow sine-wave trend plus ±15% daily noise.

PlatformWeekend behavior
Facebook~+30% impressions vs. weekdays
Instagram~+45% impressions vs. weekdays
Google~−25% impressions vs. weekdays
LinkedInDrops to ~7% of weekday volume — near-zero weekends are expected, not a bug

Evaluation

CriteriaWhat we're looking at
RequirementsAll eight required features are present and functional
Data accuracyMetrics display correctly; period-over-period deltas match; rate totals reflect the full period, not an average of daily values
UX clarityA non-technical user could read the dashboard and understand what's happening
Loading & error handlingVisible, intentional, and covers all fetch paths
Code structureData fetching in hooks, components focused on rendering, types used consistently
PolishDoes it feel finished? Edge cases handled, nothing obviously broken

We evaluate what's submitted, not what you planned to do. A smaller, tight implementation outscores a large, unfinished one.

Going Beyond

Some ideas (none required):

  • Sortable data tables beneath the charts
  • Dark / light theme toggle (persist across sessions)
  • Metric tooltips explaining CTR, CPM, Cost/Conv for non-ad users
  • Insight callouts surfacing notable observations automatically
  • Responsive layout for narrower viewports
  • Keyboard navigation — accessible date picker, tab-navigable metric cards
  • Animated transitions — loading skeletons, chart fade-ins, smooth tab switches

If you have a genuinely good idea that isn't on this list, build it. We care more about judgment — knowing what to add and what to leave out — than feature count. Bonus work should be clearly bonus; don't sacrifice core requirements to add extras.

Constraints

  • The dashboard must run in a browser.
  • The three network values (meta, google, linkedin) and four platforms are fixed — the backend does not support others.
  • Date ranges sent to /v1/metrics-insights must be 7–30 days; anything outside is rejected with a structured error.
  • Only GET requests are supported; POST, PUT, DELETE, and TRACE return 405.

How to Submit

When you're ready to turn in your work, choose one of the two methods below and email all three reviewers simultaneously.

Option A — GitHub Repository

  1. Create a new repository at github.com/new (public or private).
  2. Push your code: git push origin main
  3. If the repository is private, invite all three reviewers as collaborators before sending.
  4. Include the repository URL in your submission email.

Option B — ZIP File

  1. Archive your project folder as a ZIP.
  2. Exclude node_modules/ from the archive.
  3. Include a README.md with setup and run instructions.
  4. Name the file yourname-eulerity-hackathon.zip and attach it to your submission email.

Reviewers — email all three

Email all three reviewers at once — not just one. Include your repository link or ZIP attachment, and a brief note on anything you'd like us to pay special attention to.

If you have any issues with setup, programming questions, or need an extension, feel free to ask!