As per your situation, the view online re-executes the AMPScript that's why @today picks up the current date. I had a similar situation and here is my solution. Although notice this method would have few seconds difference compared to the @today in your non-online version.
Having (true) within the Now() function falls back to the original time when the email was sent/previewed and if you use the @today within your online version it will use the original time of the sent/previewed.
%%[
SET @today = SystemDateToLocalDate(Now(true))
IF _messageContext == "VAWP" THEN
/* Set the time to be 30 days from original send time */
SET @newTime = FormatDate(DateAdd(@today,30,'D'),'DD/MM/YYYY')
ENDIF
]%%