play icon for videos
← Academy
Collect · Other

How to track members over time

A per-year member survey can't tell you whether a member is slipping away. Here is how to carry each member forward on one record across renewals — recurring survey, cycle-over-cycle coding, and at-risk flags surfaced before renewal.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> *{box-sizing:border-box} body{margin:0;font-family:'Hanken Grotesk',-apple-system,BlinkMacSystemFont,sans-serif;background:#F7F4EC;padding:24px;display:flex;justify-content:center} .card{width:600px;max-width:100%;background:#FFFFFF;border:1px solid #ECE4D4;border-radius:20px;box-shadow:0 24px 60px -34px rgba(60,40,20,.34),0 2px 4px rgba(60,40,20,.05);overflow:hidden} .hdr{display:flex;align-items:center;gap:11px;padding:16px 20px;border-bottom:1px solid #F0E9DB;background:#F7F4EC} .hdr .n{font-family:'Newsreader',Georgia,serif;font-weight:600;font-size:16px;color:#2A2118;letter-spacing:-.2px;line-height:1.25;min-width:0} .hdr .pill{margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;color:#C05B3F;background:#F6E7E1;padding:5px 11px;border-radius:20px;white-space:nowrap;flex-shrink:0} .hdr .pill .d{width:6px;height:6px;border-radius:50%;background:#C05B3F} .tabs{display:flex;gap:0;padding:12px 14px 0;background:#F7F4EC;flex-wrap:wrap} .tab{flex:1;min-width:76px;display:flex;flex-direction:column;align-items:center;gap:5px;cursor:pointer;font-family:inherit;font-size:11px;font-weight:700;color:#8A7B66;background:transparent;border:none;border-bottom:2px solid transparent;padding:8px 4px 10px} .tab .lbl{line-height:1.2;text-align:center} .tab.on{font-weight:800;color:#C05B3F;border-bottom-color:#C05B3F} .tab .num{display:inline-flex;width:20px;height:20px;align-items:center;justify-content:center;border-radius:50%;font-size:11px;font-weight:800;color:#8A7B66;background:#F0E9DB} .tab.on .num{color:#fff;background:#C05B3F} .divider{height:1px;background:#F0E9DB} .body{padding:20px} .what{font-size:13.5px;line-height:1.55;color:#4A4030;margin:0 0 14px} .promptlbl{font-size:10px;font-weight:800;letter-spacing:1px;text-transform:uppercase;color:#B0A48D;margin-bottom:7px} .bubble{position:relative;font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:11.5px;line-height:1.55;color:#2A2118;background:#F7F4EC;border:1px solid #ECE4D4;border-left:3px solid #C05B3F;border-radius:12px;padding:13px 14px;white-space:pre-wrap;word-break:break-word} .actions{display:flex;align-items:center;gap:14px;margin-top:13px;flex-wrap:wrap} .copy{font-family:inherit;font-size:12px;font-weight:700;color:#C05B3F;background:#F6E7E1;border:1px solid #EFD5CC;border-radius:9px;padding:8px 14px;cursor:pointer} .copy.done{color:#15884F;background:#E4F1EA;border-color:#CBE6D6} .demo{font-size:12.5px;font-weight:700;color:#C05B3F;text-decoration:none} .demo:hover{text-decoration:underline} </style> </head> <body> <div class="card"> <div class="hdr"> <div class="n">How to track members over time</div> <span class="pill"><span class="d"></span>Sopact Sense</span> </div> <div class="tabs" id="tabs"></div> <div class="divider"></div> <div class="body"> <p class="what" id="what"></p> <div class="promptlbl">Copy-paste Sopact Assistant prompt</div> <div class="bubble" id="prompt"></div> <div class="actions"> <button type="button" class="copy" id="copyBtn">Copy prompt</button> <a class="demo" href="https://www.sopact.com/request-demo" target="_blank" rel="noopener">Request a demo &rarr;</a> </div> </div> </div> <script> (function(){ var D = {"title":"How to track members over time","pill":"Sopact Sense","steps":[{"n":1,"tab":"Persistent ID","what":"Give every member a persistent ID that survives renewals and email changes, so join, renew, and lapse all sit on one record.","prompt":"Assign every member a persistent Contact ID that survives renewals and email changes, and flag any member appearing more than once under different names or emails so we can merge to one record."},{"n":2,"tab":"Recurring survey","what":"Run a short recurring member survey — value, satisfaction, likelihood to renew, and one open 'what would make you stay' — coded against the member's prior response.","prompt":"Design a short recurring member survey with four items: perceived value, satisfaction, likelihood to renew, and one open question 'what would make you stay?' Keep the wording and rating scale identical to last cycle so answers stay comparable, and map each to the member's persistent ID."},{"n":3,"tab":"At-risk signal","what":"Surface at-risk and disengaging members before the renewal date, each with the source sentence.","prompt":"Read this cycle of member feedback [BATCH]. For each member, code the response against our indicators, compare to their prior cycle on the same record, score renewal risk, and flag disengagement with the source sentence — surfaced before the renewal window."},{"n":4,"tab":"Report trend","what":"Report member outcomes longitudinally — value and engagement over years, not a per-year snapshot.","prompt":"Report member outcomes longitudinally across cycles on the persistent record: trend value, satisfaction, and renewal likelihood per member and per segment. Measure value, not just attendance, and hold the rating scale constant so the trend is real."}]}; var tabsEl = document.getElementById('tabs'); var whatEl = document.getElementById('what'); var promptEl = document.getElementById('prompt'); var copyEl = document.getElementById('copyBtn'); var cur = 0; function renderTabs(){ tabsEl.innerHTML=''; D.steps.forEach(function(st,i){ var b=document.createElement('button'); b.type='button'; b.className='tab'+(i===cur?' on':''); b.innerHTML='<span class="num">'+st.n+'</span><span class="lbl">'+st.tab+'</span>'; b.addEventListener('click',function(){cur=i;render();}); tabsEl.appendChild(b); }); } function render(){ renderTabs(); var st=D.steps[cur]; whatEl.textContent=st.what; promptEl.textContent=st.prompt; copyEl.textContent='Copy prompt'; copyEl.classList.remove('done'); } copyEl.addEventListener('click',function(){ var txt=D.steps[cur].prompt; function ok(){copyEl.textContent='Copied ✓';copyEl.classList.add('done');} if(navigator.clipboard&&navigator.clipboard.writeText){ navigator.clipboard.writeText(txt).then(ok,function(){fallback(txt,ok);}); }else{fallback(txt,ok);} }); function fallback(txt,ok){ var ta=document.createElement('textarea'); ta.value=txt;ta.style.position='fixed';ta.style.opacity='0'; document.body.appendChild(ta);ta.focus();ta.select(); try{document.execCommand('copy');ok();}catch(e){} document.body.removeChild(ta); } render(); })(); </script> </body> </html>

In short: Track members over time by giving every member a persistent Contact ID that survives renewals and email changes, running a short recurring survey coded against their prior response on the same record, and surfacing at-risk members before the renewal date. Report member value and engagement as a longitudinal trend, not a per-year snapshot. In Sopact Sense the persistent ID is what lets this year's answer sit beside last year's for the same member — so you see movement, not a fresh survey each cycle.

1 · Give every member a persistent ID across the lifecycle

Membership data usually resets at every renewal — a new form, a new row, no thread back to who this member was last year. The fix is one persistent Contact ID per member that survives joins, renewals, lapses, and email changes, so the whole lifecycle sits on a single record. Assign it at first contact, and flag duplicates — the same person under a different email or name — so the history stays on one ID instead of splitting into two half-records.

Assign every member a persistent Contact ID that survives renewals and email changes, and flag any member appearing more than once under different names or emails so we can merge to one record.

2 · Run a short recurring member survey

You do not need a long annual questionnaire; you need the same short survey every cycle. Ask four things — perceived value, satisfaction, likelihood to renew, and one open "what would make you stay?" — and keep the wording and rating scale identical each time so answers stay comparable. Because every response writes to the member's persistent ID, this cycle's answer can be read against the last one.

Design a short recurring member survey with four items: perceived value, satisfaction, likelihood to renew, and one open question "what would make you stay?" Keep the wording and rating scale identical to last cycle so answers stay comparable, and map each to the member's persistent ID.

Expected output. A four-item recurring instrument mapped to the persistent ID, with the rating scale locked to prior cycles so trend is real. Input: your current member survey and the persistent IDs. Output: a comparable, repeatable member survey.

3 · Surface at-risk members before renewal

The point of tracking is to act before a member lapses, not to explain it afterward. Read each cycle of feedback the week it arrives, code it against your indicators, compare it to the member's prior cycle on the same record, and score renewal risk — flagging disengagement with the source sentence so a named owner can follow up before the renewal window opens.

Read this cycle of member feedback [BATCH]. For each member, code the response against our indicators, compare to their prior cycle on the same record, score renewal risk, and flag disengagement with the source sentence — surfaced before the renewal window.

Expected output. A per-member renewal-risk score, the movement since their last cycle, and a flag list of disengaging members each with the source sentence and a suggested owner. Input: this cycle's member feedback on the persistent IDs. Output: a scored at-risk watch list surfaced before renewal.

GRADE: green | value + satisfaction trend | same scale, compared on one ID; amber | renewal risk | scored from a single cycle, no prior to compare; red | disengagement flag | member not yet on a persistent ID, history split

Green is a member whose value and satisfaction are trended on one ID against an identical prior scale. Amber is a renewal-risk score drawn from a single cycle because there is no prior response to compare. Red is a member whose history is split across IDs, so no real trend exists until the records are merged.

4 · Report member outcomes longitudinally

Finish by reporting member outcomes as a trend, not a per-year snapshot. On the persistent record, trend value, satisfaction, and renewal likelihood per member and per segment across cycles — and measure value, not just attendance, so the story is whether membership is worth it rather than how many events someone showed up to.

Report member outcomes longitudinally across cycles on the persistent record: trend value, satisfaction, and renewal likelihood per member and per segment. Measure value, not just attendance, and hold the rating scale constant so the trend is real.

Tricks, tips, and troubleshooting

Measure value, not just attendance. Showing up is not the same as getting value. A member can attend every event and still not renew — the open "what would make you stay?" often catches that long before the attendance count does.

Keep the same rating scale each year. A trend is only real if the scale never moves. If you change a 1–5 satisfaction question to a 0–10 scale mid-stream, this year's number cannot be compared to last year's on the same record.

Never re-ask what the record already holds. If a member told you their renewal driver last cycle, do not ask again from scratch — read it off the record and confirm what changed. Longitudinal tracking should feel lighter each year, not heavier.

Improve your coding accuracy with your own language. Point the Assistant at your program or membership page so it codes feedback against your value language and indicators rather than generic categories.

Read our membership page [URL] and code this cycle of feedback against our own value and indicator language, so at-risk flags reflect what our members actually said.

Frequently asked questions

How do you track members over time?

Track members over time by giving every member a persistent Contact ID that survives renewals and email changes, running a short recurring survey — value, satisfaction, likelihood to renew, and one open 'what would make you stay' — coded against each member's prior response on the same record, and surfacing at-risk or disengaging members before the renewal date. Reporting is longitudinal rather than a per-year snapshot. In Sopact Sense the persistent ID is what lets this year's answer sit next to last year's for the same member, so engagement and value show up as a trend instead of a fresh survey each cycle.

Why use a persistent ID instead of an annual member survey?

An annual member survey that starts fresh each year cannot show whether a specific member's satisfaction rose or fell, because this year's response is not joined to last year's. A persistent Contact ID that survives renewals and email changes keeps every cycle on one record, so movement — a member sliding from satisfied to at-risk — is visible before the renewal window rather than discovered after they lapse.

How do you spot at-risk members before renewal?

Spot at-risk members by coding each cycle of member feedback against your indicators, comparing it to the same member's prior cycle on the same record, scoring renewal risk, and flagging disengagement with the source sentence — all surfaced before the renewal window opens. In Sopact Sense the comparison runs on the persistent ID, so a drop in value or a lukewarm open answer is caught while there is still time to act, not at the annual review.

Related from the Academy

Ready to try it for yourself?

Open Sopact Sense, paste your program description, and put it to work.

Try in Sopact