A reddit marketing degree, taken literally. 8 courses. 1 registrar. 1 live grader. No PDFs.
Search this keyword and you get two camps. Camp one: Reddit threads arguing whether a college marketing degree is worth the tuition. Camp two: Udemy, Coursera, and Reed selling a “Reddit marketing certification” that is a frozen PDF with no rubric. S4L publishes a third option. A curriculum of 8 named courses, a registrar that enrolls every reply drafter in one course per session, and a grader that rewrites the syllabus every time the posts table updates. The file is scripts/engagement_styles.py. This page is the course catalog.
Why the SERP reads like a shrug
The top results for “reddit marketing degree” split into three buckets. Reddit threads where a student asks if a marketing degree is worth it (AnyPromo reposts one that went viral). Online course vendors selling a generic Reddit marketing certification (Udemy, Coursera, Reed, New Skills Academy, UKSM). One Think Orion post on how universities should market themselves on Reddit. None describe an actual curriculum you could hand someone. All three buckets assume “there is no degree” and proceed to teach tactics.
S4L took the keyword literally. If a Reddit marketing degree existed, here is what it would look like: a course catalog, a registrar, a grader, and a transcript. Those four nouns map cleanly to four artifacts already in the codebase.
Course catalog → registrar → drafter → transcript → grader → next syllabus
The four numbers that define the program
Every other claim on this page expands on one of these. They are the structural spine of a curriculum that does not pretend to be finished.
The catalog
Eight courses. Each one a first-class dict key.
Numbering here is editorial. Inside the code, every course is just a key under the STYLES dict (and “recommendation” is added to REPLY_STYLES on line 92). The descriptions, openers, preferred subs, and failure notes below are quoted from the source, not paraphrased.
101 · critic
Point out what is missing, flawed, or naive. Reframe the problem. Example opener: 'The part that breaks down is...'. Elective area: r/Entrepreneur, r/smallbusiness, r/startups. Failing grade: nitpicking without a non-obvious insight.
110 · storyteller
First-person narrative with specific details (numbers, dates, names). Lead with failure or surprise, not success. Hard rule: never pivot to a product pitch.
120 · pattern_recognizer
Name the pattern or phenomenon. 'This is called X, I've seen it play out dozens of times across Y.' Authority through recognition, not credentials. Strongest in r/ExperiencedDevs.
201 · curious_probe
One specific follow-up question about the most interesting detail. Include 'curious because...' context. Banned elective on Reddit. Only one question per reply, never multiple.
210 · contrarian
Take a clear opposing position backed by experience. 'Everyone recommends X. I've done X for Y years and it's wrong.' Empty hot takes get destroyed. Requires credible evidence.
301 · data_point_drop
Share one specific, believable metric and let the number do the talking. '$12k in a month,' not 'a lot of money.' No links. Numbers must be believable, not impressive.
310 · snarky_oneliner
Short, sharp, emotionally resonant observation. One sentence max. Validates a shared frustration. Banned elective on LinkedIn and GitHub. Never in small, serious subs.
410 · recommendation
Reply-only course. Recommend a project from config.json, casually, never as self-promotion. Capped at 20% of all replies by the style sampler.
The registrar, in code
Every reply drafter reads this dict at spawn time. If a course name is not in here, the drafter cannot declare it. The catalog is closed-set on purpose: a vocabulary of 8 names is short enough to debug.
The grader
How the syllabus gets re-ranked, on every single run
There is no judge. No external classifier. The rubric is a single SQL query against the project’s own posts table, split into thirds by avg_upvotes. The output is three lists of course names that the drafter’s prompt then instructs it to mix at roughly 60/30/10.
“A style with fewer than 5 trusted samples is forced into secondary, regardless of its noisy average. Explore replaces overfit.”
engagement_styles.py line 129
What the grader prints, on a warm database
Illustrative output. The real values are read live at drafter spawn. This is what any operator sees when they manually re-run the grader for the reddit/replying context.
Banned electives
The courses that exist in the catalog but cannot be taken here
Every real university carries a catalog larger than any single student’s transcript. Some courses are not offered at some campuses. S4L’s campuses are platforms: reddit, twitter, linkedin, github, moltbook. Each platform has a list of banned courses in PLATFORM_POLICY[platform]['never']. The drafter never sees banned courses as options.
| Feature | Generic Reddit marketing guide | S4L curriculum rule |
|---|---|---|
| curious_probe | allowed on Twitter, LinkedIn, GitHub, Moltbook | BANNED on Reddit (PLATFORM_POLICY['reddit']['never']) |
| snarky_oneliner | dominant on large Reddit subs and Twitter | BANNED on LinkedIn and GitHub |
| recommendation | core to every 'content marketing' playbook | Capped at ~20% of replies, never appears in posting pipeline |
| 'pleaser/validator' style | taught in most engagement guides | Explicitly named as the lowest-performing style and avoided across all platforms |
| Content length | 'keep it short' or 'keep it substantive' (pick one) | Bimodal: either <100 chars (1 punchy sentence) or 4-5 sentences. The 2-3 sentence middle is the dead zone. |
| Opening words | no guidance, or 'start with a hook' | Must start with 'I' or 'my'. Banned openers: 'exactly', 'yeah totally', '100%', 'that's smart'. |
Academic mechanics
How a single reply actually gets graded
Five steps from catalog to transcript. Every step is in the source and every step is checkable in isolation. The flow is linear; it never branches back to the operator for a judgment call.
Every drafter spawns with a fresh rubric
When engage_reddit.py or post_reddit.py opens a new Claude session for a single reply, the first thing it does is call get_styles_prompt('reddit', context='replying'). That call re-executes the SQL. Two drafters spawned ten minutes apart can see different tiers.
This is the opposite of a static rubric. A traditional marketing curriculum teaches the same 8 tactics in the same order every year. The S4L registrar rewrites the syllabus between morning and afternoon if the posts table changes.
Banned electives are applied before grading
PLATFORM_POLICY[platform]['never'] is a brand gate, not a performance gate. Even if curious_probe led Reddit's avg_upvotes, it would still be removed before tiering runs. Rules come before results. This is where 'degree' diverges from 'data science project.'
Sample-size floor forces exploration
MIN_SAMPLE_SIZE is 5. A style with 3 samples and a wild average like 80 upvotes does not get promoted to dominant; it gets forced into secondary as 'explore.' The drafter is told to test it until the sample is trustworthy. This is how the curriculum avoids overfitting to a single viral post.
Cold start surrenders to explore-everything
If the posts table has zero rows for this platform, every non-banned style lands in secondary. Nothing is dominant, nothing is rare, every course is equally worth attending. The curriculum does not guess an order until the data earns one.
The student (Claude) declares its major in writing
Every reply output JSON must include {"engagement_style": "<name>"}. That field gets logged to posts.engagement_style in the database. The grader reads from this exact column on the next run. No external scoring. No classifier. Students grade the next class of students.
Which means the curriculum has a feedback loop no Udemy course can replicate: your output becomes the next student's input. Every published Reddit marketing certification ships a frozen PDF.
The anchor fact, for anyone planning to copy this
On line 129 of scripts/engagement_styles.py there is a single line:
MIN_SAMPLE_SIZE = 5That constant is the entire difference between a curriculum that overfits to its last viral comment and one that keeps exploring. Set it to 1 and one lucky storyteller post promotes storyteller to “dominant” for weeks. Set it to 20 and nothing ever leaves “secondary” because a single-operator Reddit program cannot produce 20 samples per style per content_angle. Five is the smallest floor that outruns one-off randomness without starving the explore pool. It also happens to match the Poisson heuristic for “this count is not zero by accident.”
If you adopt only one piece of the curriculum, adopt this constant. The rest is elaboration.
Audit your own Reddit program against this curriculum
Open scripts/engagement_styles.py on GitHub. Compare its 8 courses to whatever taxonomy your team is currently running on. If you do not have a taxonomy, you are running the 'pleaser/validator' style by default, which the file names as the lowest-performing style across all platforms.
Open engagement_styles.py →Frequently asked
What exactly do you mean by a 'reddit marketing degree'? Is this a real program?
No, it is not an accredited degree. It is a descriptive frame for the curriculum S4L hardcodes inside scripts/engagement_styles.py. The file defines 8 named engagement styles (critic, storyteller, pattern_recognizer, curious_probe, contrarian, data_point_drop, snarky_oneliner, recommendation), one registrar (the STYLES dict), and a grader (get_dynamic_tiers) that re-ranks the styles by live avg_upvotes from the local posts table. Every Reddit reply drafted by the pipeline must declare which 'course' it took, that declaration is logged, and the next drafter reads those logs to decide which courses to emphasize. The frame 'degree' captures the structural fact that this is coursework with prerequisites, forbidden electives, and a live rubric, not a tactical checklist.
Where is the curriculum file and how do I open it?
/Users/matthewdi/social-autoposter/scripts/engagement_styles.py. Open it and the entire syllabus is the top of the file: STYLES dict at lines 15-86, PLATFORM_POLICY at lines 104-125, MIN_SAMPLE_SIZE = 5 at line 129, _fetch_style_stats at lines 132-159, get_dynamic_tiers at lines 162-211, and get_styles_prompt at lines 216-284 (which is what the drafter actually reads). Every piece of behavior described on this page traces back to one of those spans. Nothing is abstracted into a third-party service.
Why 5 samples as the minimum? Why not a statistical test?
A statistical test would be more correct and more expensive. The trade-off here is deliberate: 5 is a low bar that kills two failure modes cheaply. First, it blocks a single viral post from anointing a whole style as 'dominant.' Second, it survives cold start, where a platform has 0-3 posts of any kind and a z-score would be meaningless. With n=5 as the floor, every style gets at least 5 real attempts before its avg_upvotes is treated as a signal. That buys enough samples to be non-accidental without introducing scipy as a dependency. The choice lives at line 129 as a bare constant, not a config variable, because raising it further would starve the explore pool and lowering it would reward noise.
Why is curious_probe banned on Reddit but allowed everywhere else?
Reddit replies with a single question read as 'AMA bait' or 'survey post' and consistently underperform. The same opener on Twitter or LinkedIn reads as professional curiosity and performs normally. This is not a measurement from the posts table; it is a hardcoded brand rule, the kind of rule that exists because it was learned once painfully and never needs to be re-learned. PLATFORM_POLICY['reddit']['never'] = ['curious_probe'] enforces it at the prompt layer: the drafter never sees curious_probe as an option for a Reddit reply. Even if the posts table later showed curious_probe's avg_upvotes climbing, the ban would still apply. Rules gate results.
What is the 'dead zone' for Reddit reply length?
The content rule in get_content_rules('reddit') is explicit: 'Go BIMODAL: either 1 punchy sentence (<100 chars, highest avg upvotes) or 4-5 sentences of real substance. AVOID the 2-3 sentence dead zone.' The pattern comes from observing that 2-3 sentence Reddit replies look like they were copy-edited by marketing: too long to be casual, too short to be substantive. They read as 'a pro wrote this' and get filtered by readers' spam detectors. One sentence reads as native. Five reads as an expert actually helping. Three reads as an ad. The rule is enforced only in prompting; there is no programmatic length gate, so bimodal compliance is measured in the drafter's output, not the pipeline layer.
Does the grader ever forget? Or does an old post keep influencing the rubric forever?
The query filters WHERE status='active' AND engagement_style IS NOT NULL AND our_content IS NOT NULL AND LENGTH(our_content) >= 30 AND upvotes IS NOT NULL. Anything archived, deleted, or soft-closed (status != 'active') falls out of the grade. Posts with no recorded upvote data are invisible to the grader. There is no time-decay weight, which is deliberate: a style that stopped working six months ago is still worth remembering as 'rare,' because the mechanism of why it failed usually still applies. If a post is truly no longer representative, the operator flips its status. Everything else sits in the grade forever or until upvote counts are refreshed by scrape_reddit_views.py.
How does 'recommendation' differ from the other courses?
Two ways. One, it only exists in the reply pipeline (REPLY_STYLES = VALID_STYLES | {'recommendation'} at line 92), not the posting pipeline. You cannot open a brand-new Reddit thread in the recommendation style. Two, it carries an explicit cap: the styles prompt instructs the drafter to use it in at most 20% of replies. The reason is structural: recommendation is the only style that links to a product (from config.json). Overusing it shifts the account from contributor to advertiser in Reddit's implicit ranking, which is the fastest way to lose the ability to post at all. The 20% cap is a prompt-level instruction, not a hard guard. Prompt-level is sufficient because the drafter's own output is logged, and a pattern of recommendation-heavy replies would show up in the posts.engagement_style column and be visible in any audit.
Which styles show up as 'dominant' on Reddit in practice?
That varies by content_angle and changes whenever upvote data changes. Style leaderboards are read live per run via _fetch_style_stats, so any claim like 'storyteller dominates Reddit' would be wrong the moment the posts table updates. What is stable: curious_probe never appears (banned), recommendation is capped at 20% (cap), 'pleaser/validator' style (marked explicitly in the styles prompt as lowest engagement) is avoided across all platforms. Which of storyteller, data_point_drop, pattern_recognizer, contrarian, or critic wins on any given week depends on the content_angle's subreddits and their current voting patterns. A guide that publishes a fixed ranking is lying about the mechanism.
Can this 'curriculum' be ported to a human-operated Reddit program with no automation?
Yes. The STYLES dict is language, not software. Treat it as a taxonomy for your own comments: tag each reply with one of the 8 style names in a spreadsheet, record upvotes after 48 hours, compute your own rolling avg per style, forbid curious_probe on Reddit, cap recommendations at 20%, never produce 2-3 sentence replies, and never start with 'exactly,' 'yeah totally,' '100%,' or 'that's smart.' The whole point of publishing the source is that the rubric survives outside the pipeline. The pipeline only buys speed.
Why is this better than a Reddit marketing course on Udemy or Coursera?
A prerecorded course is a frozen rubric. It teaches 8 tactics in a fixed order and never re-ranks them. If storyteller-style replies stopped working on r/Entrepreneur tomorrow, the course would still recommend them. S4L's grader recomputes the rank on every run from your own posts table, which means the curriculum decays fast and updates fast. Second, the Udemy/Coursera courses almost never name a style and almost never name a forbidden one. Their mental model is 'here is what works,' ours is 'here are 8 hypotheses, these 1-2 are currently supported, these are explore, this set is banned for brand reasons.' The degree-frame is more honest about what is known and what is still being tested.
What is the simplest way to adopt just one idea from this curriculum?
Adopt MIN_SAMPLE_SIZE = 5 for yourself. Pick any way you segment your Reddit comments (by style, by subreddit, by opener, by time of day). Refuse to call any segment 'the winner' until you have at least 5 comments in that segment. That one rule kills most of the bad generalizations people make after two or three lucky comments. The rest of the curriculum (named styles, platform bans, 20% recommendation cap, bimodal length) matters more as you scale, but the 5-sample floor matters from day one.
This page treats the keyword literally. Every file path, line number, and constant referenced above is real.
Source of truth: scripts/engagement_styles.py