Here is a thread with a similar discussion.
If I am interpreting the logic correctly you could move all of this to PostUserTrackingAction, specifically this part:
// Initialize tracker for new primary gammas - only once per track
if (fPrimaryGammaTracker.find(trackID) == fPrimaryGammaTracker.end()) {
PrimaryGammaInfo info;
info.initialEnergy = preStepEnergy;
info.isFirstEntry = true;
info.initialMaterial = material->GetName();
info.initialLayerID = layerID;
info.hasExited = false;
info.depositedEnergy = 0.0;
info.transferredToSecondaries = 0.0;
info.exitEnergy = 0.0;
info.trackedSecondaries = std::set<G4int>();
fPrimaryGammaTracker[trackID] = info;
You could define these parameters in EventAction and then call it only in the PostUserTrackingAction since 1 and only 1 particle has a trackID of 1. That would simplify your code immensely and lead to a slight improvement since TrackingActions are called far less often than steps.
If you want to differentiate primary compton vs PE events than you will instead put all of that info class structure into your own UserTrackingInfo class. Specifically follow the example of Run and Event 01 and pass that info to all descendants by this cookbook. You could set a field to be “first interaction” that is either “compton” or “photoelectric” and then record all energy deposited in your detector into an ntuple that includes that field so you can filter it however you please afterward.