Is there some kind of part I can attach to the bottom of the shaft that would hold the optic sensor and disc?
If you can replace the screw on the end with a longer one, it should be easy to attach a 3d printed encoder wheel for orientation -- you shouldn't even need the flange shaft coupler.
The more difficult part of the mod will be to make a mount for the LED and sensor that attaches to the clip-on spinner opto assembly.
- Maybe attach the mount using the two screws that connect the spinner opto assembly PCB to the black plastic clip-on assembly. You might need slightly longer screws for this.
It should be easy to remix the 3D printable mount available
here on Thingiverse.
- That mount was designed for using Adafruit 2167
3mm beam break sensors in skee-ball machines.

I'm guessing the disc would only need one hole, correct?
Almost right. You need an encoder wheel with one tooth.
When the spinner
is pointed at 12 o'clock, the opto is blocked so the data line is at logic LOW.
- With an "active low" encoder, that LOW is seen as a button being pressed -- same as pressing a button connects ground to the encoder input.
When the spinner
is not pointed at 12 o'clock, the opto isn't blocked so the data line is at logic HIGH.
- With an "active low" encoder, that HIGH is seen as a button not being pressed.
Here's the code to generate a one-tooth orientation encoder wheel in OpenSCAD.
- Adjust the variables as desired, render it, and export it as an .STL to make a custom 3d printable model.
// 720 Mod Orientation Encoder Wheel
// - WIP
/////////////////////////////
// Define variables
/////////////////////////////
WheelThick = 2.4; // Encoder wheel thickness
WheelDia = 40; // Encoder wheel diameter
SpacerThick = 8; // Spacer thickness
SpacerDia = 10; // Spacer diameter
ToothWidth = 4; // Encoder wheel tooth diameter
ToothLength = 6; // How far the tooth sticks out past the wheel.
InnerDia = 5; // Center hole diameter
// The inner diameter value may need to be *very slightly* larger to account for the 180-sided polygon used to render circles -- see "undersized holes" at https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder
$fn=180; // Number of fragments (polygon sides) used to render a circle
/////////////////////////////
// Make the part
/////////////////////////////
difference() { // Wheel, spacer, and tooth minus center hole
union(){ // Wheel, spacer, and tooth
color("red")
translate([0,0,WheelThick/2])
cylinder(WheelThick, d=WheelDia, center=true); // Wheel
color("gray")
translate([0,0,WheelThick + (SpacerThick/2)])
cylinder(SpacerThick, d=SpacerDia, center=true); // Spacer
color("blue")
translate([0,-WheelDia/2,WheelThick/2])
cube([ToothWidth,ToothLength*2,WheelThick], center=true); // Tooth
} // End wheel, spacer, and tooth
translate([0,0,(WheelThick + SpacerThick)/2])
cylinder(WheelThick + SpacerThick + 0.1, d=InnerDia, center=true); // Center hole
} // End wheel, spacer, and tooth minus center hole
//
Scott