This cannot be done in a custom action. It's true that you can set the ProductName property in a custom action (such as a type 51) early in the install and that will indeed change the name in the UI, but it will NOT change the name of the installed product - it will remain the same as the original value. For example, enumerating installed products will return the original name.
So the only good way to do this is to modify the ProductName in the MSI file before you launch it. You would have a launching program that modifies the MSI file and then installs it. The MSI file is a database that can be modified in the Property table to change the value of ProductName. This example will give you the general idea:
How do I add/update a property inside an MSI from the command-line?
but basically you open the open the database (MsiOpenDatabase or equivalent) then MsiOpenView with a SQL such as:
"UPDATE Property SET Property.Value = 'Your variable' WHERE Property.Property = 'CurrentProductName' "
then MsiViewExecute and close handles etc. Details depend on your preferred coding language environment.
This is not an ideal solution because if your MSI file is digitally signed you have tampered with it and it is no longer correct.
Another way is to generate a transform file, based on altering a copy of the MSI file. If you make a copy of the MSI file, and then do the alteration of ProductName as above you can then do an MsiDatabaseGenerateTransform() call which will generate a transform file, a .mst file, the difference between the two MSI files. You then install the original unaltered MSI file with a command line that includes TRANSFORMS=[the .mst file] which will update the ProductName and start the install.
None of this is very easy because Windows Installer products are not designed to have dynamic product names. Maybe historically and before Windows Installer setups this was more practical, but not in MSI setups.