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 expected. At least one requirement below is intentionally underspecified — we want to see you catch it and ask. Reach out with your questions and proposed resolution before finalizing that part of the build; document the decision in your README. The questions you ask matter as much as the code you write.
What You Must Build
-
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-summaryfor this page (fixed 30-day rolling window, no date parameters needed). - 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.
- 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.).
- 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.
- 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.
- 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.
Tech Stack
The following are required:
| Layer | Requirement |
|---|---|
| Language | TypeScript |
| Framework | React |
| Styling | styled-components |
| Routing | react-router-dom |
| Charts | A chart library — we suggest react-google-charts, but any equivalent is fine |
| CSV export | A 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
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.
| Parameter | Required | Values |
|---|---|---|
network | Yes | meta | google | linkedin |
startDate | Yes | ISO date, e.g. 2026-05-27 |
endDate | Yes | ISO 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": "..." }.
| Status | Code | When it occurs |
|---|---|---|
| 400 | MISSING_PARAM | A required parameter is absent |
| 400 | INVALID_NETWORK | network is not meta, google, or linkedin |
| 400 | INVALID_DATE_FORMAT | A date is not in YYYY-MM-DD format |
| 400 | INVALID_DATE_RANGE | endDate is before startDate |
| 400 | WINDOW_TOO_SMALL | Range is fewer than 7 days |
| 400 | WINDOW_TOO_LARGE | Range exceeds 30 days |
| 404 | NOT_FOUND | Path does not match either endpoint |
| 405 | METHOD_NOT_ALLOWED | Non-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.
| Platform | Weekend behavior |
|---|---|
| ~+30% impressions vs. weekdays | |
| ~+45% impressions vs. weekdays | |
| ~−25% impressions vs. weekdays | |
| Drops to ~7% of weekday volume — near-zero weekends are expected, not a bug |
Going Beyond
Once the core requirements are solid, feel free to add features that showcase your skills. 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-insightsmust be 7–30 days; anything outside is rejected with a structured error. - Only
GETrequests are supported;POST,PUT,DELETE, andTRACEreturn405.
How to Submit
Push your project to a public GitHub repository and submit the link using the form below.
Make sure your repo includes a README.md with setup and run instructions.
If you have any issues with setup, programming questions, or need an extension, feel free to ask!