feat: Add survey completion time tracking and display for analytics.#6708
feat: Add survey completion time tracking and display for analytics.#6708lakshita10341 wants to merge 10 commits intoWikiEducationFoundation:masterfrom
Conversation
0904edb to
4a60419
Compare
I haven't look at the code yet so I had this question. |
| t.integer :survey_notification_id | ||
| t.datetime :started_at, null: false | ||
| t.datetime :completed_at | ||
| t.integer :duration_in_seconds |
There was a problem hiding this comment.
duration_in_seconds is this required ? Can't the time to calculate SurveyCompletionTime be obtained from started_at and completed_at
There was a problem hiding this comment.
yes, sorry i missed it. The duration column is not required, so i will remove it in next commit.
Yes, this will create a record in db, with some starting time and 'nil' ending time if the user does not submit the survey. I added a |
|
I don't think it makes sense to add a separate table for survey completion time. We already have a table that represents a set of survey responses being submitted, which is |
That is right, this approach will keep the database clean. But the main reason I initially considered a separate table was to track abandonment rates and avoid data duplication issues. Since Also, since a Survey can contain multiple Please let me know, if adding field to |
|
That's a good point about tracking abandonment rates, and I think I'm open to a new table if that's part of the design. The name of such a table should be clearer, as |
|
Will |
|
That sounds reasonable, although 'session' implies each record is limited to a single session, with different records if a user starts and abandons a survey, then later starts and completes it. Would that be how it works? |
|
At every 'Start' attempt, there will be a new session record created, which lets us accurately track abandonment vs. completion rates. For the CSV export and duration analytics, we then only look at the successfully completed session. |
|
Is index on all three required ? add_index :survey_sessions, :survey_id
add_index :survey_sessions, :user_id
add_index :survey_sessions, %i[survey_id user_id] |
Yeah, Since we have composite index on |
|
Can you also point to which part of the code is using this |
add_index :survey_sessions, %i[survey_id user_id]I am referring to this part of code |
|
No I mean in the actual Survey codebase |
|
That might be confusing what I just said. I mean which |
|
One problem with adding indexes early is cardinality. Make sure you’ve checked in MySQL that the query planner is actually using both indexes. |
While the query is not using directly both the indexes, but this composite index still helps here: SurveySession.where(survey_id: id).index_by(&:user_id)Although the |
|
hmm can you show me the query planner using |
|
Sorry I was wrong. Since we are using |
keeping index on only |
| class SurveySession < ApplicationRecord | ||
| belongs_to :survey | ||
| belongs_to :user | ||
| belongs_to :survey_notification, optional: true |
There was a problem hiding this comment.
What is the purpose of optional here ?
There was a problem hiding this comment.
If the user takes a survey without clicking on the email link, then survey notification id will be null. That's why optional is used.
| t.timestamps | ||
| end | ||
|
|
||
| add_index :survey_sessions, :user_id |
There was a problem hiding this comment.
After removing it from Composite Index why add it separately again? Where is this being used ?
There was a problem hiding this comment.
Sorry, I meant to remove it alongside the composite index but it was an oversight. I've removed it now. I realized we can add it back if in future we need it.
|
Thanks for the changes. I will have a look within the next few days, |


What this PR does
Adds survey completion duration tracking so admins can see how long users take to complete surveys.
Closes #6355
Problem: The survey system captures what users answered but has no way to measure how long each submission takes. This makes it difficult to identify surveys that are too long or confusing.
Solution: A new
survey_completion_timestable records start/end timestamps for each survey submission. The frontend sends a POST when the user starts the survey, and a PUT when they submit. Duration is computed server-side.Changes
Backend:
SurveyCompletionTime), and controller withstart/completeactionsPOST /survey/startandPUT /survey/completeSurvey#to_csv) now includesduration_secondsas the last columnFrontend:
Survey.jssends tracking requests on survey start and completion (fails silently to never block the survey)Admin views:
Edge cases handled:
--for all stats (no backfill needed)AI usage
I used Gemini to help implement this feature. The AI was used for:
Screenshots
Before:

After:

##Open concerns