First, you need to convert your instances into real geometry, because you cannot store different data into the same object data (Instances share the same object data). It is not efficient in calculating and memory, so do it only if you need.
To convert data, you have to use Realize Instances node. It can transfer data from instance to realized geometry only in 3.1 (remove old one and add new one in 3.1 this is why). So you have to get this build at https://builder.blender.org
Here is the simple set up:
You can note that I use Capture Attribute with "Instance" setting to pass a value from instance to realized geometry. In my case it's just random color, you may build your own node setup.
When you send the data to output, you need to store it somewhere. In my case, I use vertex color to save the data. This is the output section of geometry nodes modifier is used for:
Then finally you can use this data in shader using the Attribute node:
If you find that UVMap is broken, use also Attribute node to get the UV, this is a known issue.