I added a LEFT JOIN on INSERTED to check if duplicates are in the source. My source query now looks like:
SELECT
CASE
WHEN pk.id IS NULL AND i2.idProduct IS NULL
THEN i.description
ELSE
i.description + '_' + CAST(i.idProduct AS VARCHAR)
END [NewProductKey]
, i.idProduct
FROM
INSERTED i
LEFT OUTER JOIN ProductKeys pk ON pk.id <> i.idProduct AND pk.ProductKey = i.description
LEFT OUTER JOIN INSERTED i2 ON i2.description = i.description AND i.idProduct <> i2.idProduct
This is works OK for me - when there are 2 products in the source with the same description, both will have its id appended to the key.
However if there's a way to have the key of the first product without the id - just the description - and have the rest with the id, that would be ideal.