Why won’t this work?
[[*productSpecialPriceExpiry:strtotime:gt=`[[!getDate]]`:then=`
<div class="badge">Kampanj</div>
`:else=``]]
If I call getDate cached (without !) it works, but I’m worried it might at some point cache the date and give the wrong output…?
Just an idea: Have you tried modifying the [[!getDate]] to match exactly your given format from your TV?
// e.g.
[[!getDate:date=`%Y-%m-%d`]]
You could also format the TVs given output to match:
[[*productSpecialPriceExpiry:strtotime:date=`%Y-%m-%d`:gt=`[[!getDate:date=`%Y-%m-%d`]]`:then=`
<div class="badge">Kampanj</div>
`:else=``]]
This would only make sense if for some reason [[getDate]] and [[!getDate]] have different output formats, but maybe it’s worth a shot…
maybe
[[!*productSpecialPriceExpiry:strtotime:gt=`[[!getDate]]`:then=`
<div class="badge">Kampanj</div>
`:else=``]]
would do it?
Yes!!! @bruno17’s suggestion with the extra exclamation mark did the trick it seems 
Just as a side note, oddly enough it works without the extra exclamation mark in a chunk:
[[+tv.productSpecialPriceExpiry:strtotime:gt=`[[!getDate]]`:then=`
<div class="badge">Kampanj</div>
`:else=``]]

Thanks both of you for your help!
this works, because the placeholder in this case is parsed while iterating over the items and its not cached in this case.