Backend Development Service For Market Research And Strategy
- Posted 1 month ago
- Remote
Description
Gig Overview:The goal of this gig is to develop a scalable backend microservice for managing Marketing Research and Strategy, using Node.js + TypeScript and MySQL with Prisma ORM for scalable and efficient data storage . The service will handle managing operations for research , survey , and reports including aggregation of survey responses and statistical calculations for dashboards.
Github Repository:
The project structure for this application has been established.
Clone from: https://github.com/suburban-fiber-company/Market_Resesrch_Strategy.git
Switch to the develop branch to continue your work and ensure compliance with the established structure. Do not work outside of these contracts.
Scope of Work
The backend microservice will provide endpoints for managing research, survey and reports, ensuring seamless CRUD operations, statistical calculations, and correlation analysis for dashboards, security, and performance optimization. The solution should prioritize clean code and thorough documentation.
Develop endpoints for the following scenarios:
-Create New Market Research Guide
Endpoint: POST /api/v1/market-research
Description:
-Validates request payload using Joi.
-Stores the research details in MySQL via Prisma ORM.
Sample Request Body:
{
"title": "Market Research Backend API",
"objective": "Build scalable Node.js backend for research/survey data management.",
"target_audience": "Marketing teams & analysts",
"Market_size_and_growth_rate": "$81B industry, 5% CAGR",
"competitor_analysis": "Competes with Qualtrics, SurveyMonkey",
"consumer_analysis": "Needs: real-time analytics, easy exports",
"conclusion": "Deliver secure, documented API by Q1 2025"
“created_by”: “John Doe”,
}
Field Descriptions:
title (string, required) - The title of the research
objective(string, required) - The objective of the research
target_audience (string, required) -
market_size_and_growth_rate(string, required) -
Copetitor_analysis (string, required) -
consumer_analysis (string, required) -
conclusion (string, required) -
created_by (string, required) - Name of the person that created the market research guide.
Sample Response :
{
"status": "success",
“Message”: “Market research guide saved successfully”,
"data": {return saved details }
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-
Get All Market Research Guide (200 OK)
Endpoint: GET /api/v1/market-research
Description: Retrieve all market research in DESC order with optional filtering by title and market_size
Query Parameters:
-search: (optional) keyword search.
-title: (optional) filter by title.
-date_modified: (optional) filter by date it was updated
-sort_by: (optional) created_at (asc/desc).
Sample Response:
{
"status": "success",
"message": "Market Research Guide Fetched Successfully",
"data": {
"market_research": [
{
"id": 2,
"title": "Summer Sale Launch",
"objective": "Summer Sale Launch",
"market_size_and_growth_rate":”$81B industry, 5% CAGR” ,
"competitor_analysis": "Lorem Ipsum",
"competitor_analysis": "Competes with Qualtrics, SurveyMonkey",
"consumer_analysis": "Needs: real-time analytics, easy exports",
"conclusion": "Deliver secure, documented API by Q1 2025"
“created_by”: “John Doe”,
"created_at": "2025-02-21T10:00:00Z":
"updated_at": "2025-02-21T10:00:00Z"
},
{
"id": 1,
"title": "Summer Sale Launch",
"objective": "Summer Sale Launch",
"market_size_and_growth_rate":”$81B industry, 5% CAGR” ,
"competitor_analysis": "Lorem Ipsum",
"competitor_analysis": "Competes with Qualtrics, SurveyMonkey",
"consumer_analysis": "Needs: real-time analytics, easy exports",
"conclusion": "Deliver secure, documented API by Q1 2025"
“created_by”: “John Doe”,
"created_at": "2025-02-21T10:00:00Z": ,
"updated_at": "2025-02-21T10:00:00Z"
},
],
"pagination": {
"total": 8,
"current": 1,
"from": 1,
"to": 8,
"pages": 1
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Get Single Market Research By Id
Endpoint: GET /api/v1/market-research/:id
-Fetches details of a single market-research by its ID.
Description: Retrieve detailed information about a specific market-research.
Sample Response:
{
"status": "success",
"data": {
"id": 1,
"title": "Summer Sale Launch",
"objective": "Summer Sale Launch",
"market_size_and_growth_rate":”$81B industry, 5% CAGR” ,
"competitor_analysis": "Lorem Ipsum",
"competitor_analysis": "Competes with Qualtrics, SurveyMonkey",
"consumer_analysis": "Needs: real-time analytics, easy exports",
"conclusion": "Deliver secure, documented API by Q1 2025"
“created_by”: “John Doe”,
"created_at": "2025-02-21T10:00:00Z": ,
"updated_at": "2025-02-21T10:00:00Z,
},
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "Sorry, unable to complete the operation. Please, try again"
}
-Update Market Research (200 OK)
Endpoint: PUT /api/v1/market-research/:id
Description: Updates a single market research
Request Body :
{
"title": "Market Research Backend API",
"objective": "Build scalable Node.js backend for research/survey data management.",
"target_audience": "Marketing teams & analysts",
"Market_size_and_growth_rate": "$81B industry, 5% CAGR",
"competitor_analysis": "Competes with Qualtrics, SurveyMonkey",
"consumer_analysis": "Needs: real-time analytics, easy exports",
"conclusion": "Deliver secure, documented API by Q1 2025"
“created_by”: “John Doe”
}
Sample Response:
{
"status": "success",
“Message”: “Newsletter updated successfully”,
"data": {return updated market research details }
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Create New Survey Form (201 created)
Endpoint: POST /api/v1/survey
Description: Develop an endpoint that allows a user to create a survey form with customizable questions (user should be able to create either a multiple question with options and also question that requires responder to provide short answer), and a sharable link. The form should be stored in the database and set to active to true by default.
Requirements and implementation Details:
1. survey_title (string, required) - Main title of the survey.
2. page_title (string, optional) - Title displayed on the survey page
3. The user can add multiple questions with:
question (array of objects) - Each question should include:
question_text (string, required) - The actual question
question_type (enum: “multiple_choice” or “short_answer”, required).
is_required (boolean, default: true) - Marks if the question is mandatory
For multiple_choice questions, include:
options (array of strings, required) - List of choices.
allow_multiple_selection (integer, default: 0) - If 1, behaves like checkboxes.
4. is_active (integer, default: 0) - Flag to indicate the status of the form. The form should be created in an inactive state.
5. created_by (string, required) - Name of the person creating the form. This can be gotten through the authenticated user. The API endpoint for this will be provided.
6. Upon form creation, generate a URL with the name of the survey embedded in it. (sample link. https://name_of_url/survey/:uuid). Store the full url in the database. The uuid should be saved alongside each survey.
Sample Response :
{
"status": "success",
“Message”: “survey form saved successfully”,
"data": {return saved details }
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Update the survey form active status (200 OK)
Endpoint: PATCH /api/v1/survey/:id/update
Description: This endpoint toggles the status of the survey form.
Sample request body:
{
is_active: e.g 0 or 1
}
-Submit Respondent Response (200 OK)
Endpoint: POST /api/v1/survey/:uuid/response
Description: This endpoint allows survey respondents to submit their answers. The endpoint should:
-Validate responses against the survey structure
-Store answers in the database
-handle time the responded opened the form and time they click on the submit button
-Handle required fields and respondent info
Sample Response:
{
"success": true,
"message": "Response submitted successfully",
"data": {
"id": "1",
"survey_id": "5",
// other fields in the response object including the question_id and response for each question, also the respondent name and email
"start_date": "2023-11-16T12:30:00Z",
"end_datee": "2023-11-16T12:30:00Z",
"created_at": "2025-02-21T10:00:00Z",
"updated_at": "2025-02-21T10:00:00Z"
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Get All survey (200 OK)
Endpoint: GET /api/v1/survey
Description: Retrieve all survey forms and their data in DESC order with optional filtering by query parameters..
Query Parameters:
-search: (optional) keyword search.
-title: (optional) filter by title.
-sort_by: (optional) created_at (asc/desc).
Sample Response:
{
"status": "success",
"message": "survey fetched successfully",
"data": {
"survey": [
{
"id": 1,
“title”: “”,
"created_by": "John Doe",
"number_of_questions": 10,
"number_of_responses": 10,
"survey_completion_rate": "100%"
"created_at": "2025-02-21T10:00:00Z":
"updated_at": "2025-02-21T10:00:00Z",
},
{
"id": 1,
“title”: “”,
"created_by": "John Doe",
"number_of_questions": 10,
"number_of_responses": 10,
"survey_completion_rate": "100%"
"created_at": "2025-02-21T10:00:00Z":
"updated_at": "2025-02-21T10:00:00Z"
},
],
"pagination": {
"total": 8,
"current": 1,
"from": 1,
"to": 8,
"pages": 1
}
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Get a single survey shareable link (200 OK)
Endpoint: GET /api/v1/survey/:id/shareable-link
Description: Retrieve the shareable link of a particular survey.
-Get Summary of Analytics for single survey (200 OK)
Endpoint: GET /api/v1/survey/:id/summary
Description: Retrieve analytics summary for a single survey
Sample Response:
{
"status": "success",
"message": “ survey response summary fetched successfully",
“data” {
“number_of_response” : 10,
number_of_“partial_responses” : 10,
“average_time_taken” : 5.4,
“survey_completion_rate” : 80%
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "Sorry, unable to complete the operation. Please, try again"
}
-Get all responses for single survey (200 OK)
Endpoint: GET /api/v1/survey/:id/responses
Description: Retrieve all responses for a single survey with filtering options.
Query Parameters:
-search: (optional) keyword search.
-respondent: (optional) filter by title.
-sort_by: (optional) created_at (asc/desc).
Sample Response:
{
"status": "success",
"message": “ survey responses fetched successfully",
“data” {
“responses” : [
{
“id” : 2
“full_name” : “John Doe”,
"start_date": "2023-11-16T12:30:00Z",
"end_date": "2023-11-16T12:30:00Z",
“survey_completion_rate”: “100%”
},
{
“id” : 1
“full_name” : “John Doe”,
“start_date” : 2025-03-25
“end_date”: “2025-3-27”,
“survey_completion_rate”: “100%”
},
],
"pagination": {
"total": 8,
"current": 1,
"from": 1,
"to": 8,
"pages": 1
}
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "Sorry, unable to complete the operation. Please, try again"
}
-Get single response details (200 OK)
Endpoint: GET /api/v1/survey/:id/:response_id
Description: Retrieve response details for a single response including the questions, answers, and details of the respondent.
-Create New Strategy Report (201 Created)
Endpoint: POST /api/v1/reports/strategy
Description:
-The strategy report document will be saved onto a file server (The api documentation will be shared) and will require a public_url that will be used to display it. Please, note that the file public_url will be saved into the database.
-Stores the content details in MySQL via Prisma ORM.
Sample Request Body (Form data):
Key: file_name | Value: file.doc (allowed extension: doc, docx, pdf)
Key: strategy_title | Value: Lorem Ipsum
Key: created_by | Value:John Doe
Field Descriptions:
-file_name (string, required) - The name of the uploaded document
-strategy_title (string, required) - Title of strategy document
-created_by (string, required) - Name of the person that created the report
Sample Response :
{
"status": "success",
“Message”: “Strategy report saved successfully”,
"data": {return saved details }
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Get All Strategy Reports (200 OK)
Endpoint: GET /api/v1/reports/strategy
Description: Retrieve all strategy reports in DESC order with optional filtering.
Query Parameters:
-search: (optional) keyword search.
-title: (optional) filter by title.
-sort_by: (optional) created_at (asc/desc).
Sample Response:
{
"status": "success",
"message": "Strategy Report Fetched Successfully",
"data": {
"reports": [
{
"id":21,
"title": "Summer Sale Launch",
"public_url": "path/to/file/summer-sale.jpg",
"created_by": "John Doe",
"created_at": "2025-02-21T10:00:00Z",
"updated_at": "2025-02-21T10:00:00Z"
},
{
"id": 1,
"title": "Summer Sale Launch",
"public_url": "path/to/file/summer-sale.jpg",
"created_by": "John Doe",
"created_at": "2025-02-21T10:00:00Z",
"updated_at": "2025-02-21T10:00:00Z"
}
],
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Get Single Strategy Report By Id
Endpoint: GET /api/v1/reports/:id/strategy
-Fetches details of a strategy report by its ID.
Description: Retrieve detailed information about a specific strategy report.
Sample Response:
{
"status": "success",
"data": {
"id": 1,
"title": "Summer Sale Launch",
"public_url": "path/to/file/summer-sale.jpg",
“created_by”: “John Doe”
"created_at": "2025-02-21T10:00:00Z",
"updated_at": "2025-02-21T10:00:00Z"
},
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "Sorry, unable to complete the operation. Please, try again"
}
-
Update Strategy Report (200 OK)
Endpoint: PUT /api/v1/reports/:id/strategy
Description: Updates a strategy report
Request Body :
Key: file_name | Value: file.jpeg
Key: strategy_title | Value: Lorem Ipsum
Key: created_by | Value:John Doe
Sample Response:
{
"status": "success",
“Message”: “Strategy report updated successfully”,
"data": {return updated strategy report details }
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "return appropriate error message"
}
-Get Summary of Analytics for all survey (200 OK)
Endpoint: GET /api/v1/survey/summary
Description: Retrieve analytics summary for all survey
Sample Response:
{
"status": "success",
"message": “ survey response summary fetched successfully",
“data” {
“number_of_survey” : 10,
“number_of_response” : 10,
number_of_“partial_responses” : 10,
“average_time_taken” : 5.4,
“survey_completion_rate” : 80%
}
}
Error Response (500 Internal Server Error):
{
"status": "error",
"message": "Sorry, unable to complete the operation. Please, try again"
}
Backend Developer
Proficiency in Node.js/TypeScript language for backend development.
Strong understanding of RESTful API development and integration.
Skilled in Prisma ORM (MySQL) database optimization for performance and scalability.
Required Skills:
Strong backend development using Node.js/TypeScript
Expertise in MySQL database design and architecture.
Knowledge of API security best practices, including data validation and input sanitization.
Must be familiar with the use of Joi for request validations
Strong knowledge of Joi Library for request validation
Software/Design Requirements:
Framework: Node.js/Typescript.
Database: Prisma ORM, MySQL for relational data storage.
Authentication: API Token validation
API Documentation: Swagger for endpoint documentation.
Breakdown of Common API status codes
“Please ensure all of the status codes are properly handled for seamlessly frontend integration”
400 Bad Request – The server cannot process the request due to client error (e.g., invalid JSON, missing parameters).
401 Unauthorized – The request lacks valid authentication credentials (e.g., missing or invalid token).
404 Not Found – The requested resource does not exist on the server.
422 Unprocessable Entity – The request is well-formed but contains invalid data (e.g., validation errors).
500 Internal Server Error – A generic server-side error, often due to unexpected failures in processing.
Expectations:
As a Techo chosen to participate in this gig, we have some expectations.
Timely Completion: complete each gig within the given timeframe. If the gig has not been completed within this frame, the project will be re-assigned.
Communication: Stay in touch with the Community Manager for guidance, support and feedback throughout the project. This can be done through the chat box in the My Gigs section underneath the gig description.
Work-Ethic Alignment: Make a concerted effort to comply with our standards.
It is very key that Techo pays very attentions to details so as to avoid disqualification or re-assigning of the gig
Where the project structure has been defined, it is very important that the Techo does not deviate from the established structure
Skills required
- 5 months ago
- Remote
- Intermediate
- 1 Freelancer
Gig Budget
₦10,000.00 - ₦10,000.00
- 1 month ago
- Remote
- Intermediate
- 1 Freelancer
Gig Budget
₦30,000.00 - ₦35,000.00
Integration of Resources and Onboarding feature Pages Using Vue.js 3 Composition API and TailwindCSS
- 2 weeks ago
- Remote
- Intermediate
- 1 Freelancer