As residential universities struggle to establish the level of student engagement with in-person courses that existed before the pandemic, some are looking at implementing the type of student support infrastructure that has long been in place at online universities, which typically cater to working adults juggling many priorities.
For universities looking to implement this type of technology, the Student Success Hub by Salesforce.org could be a good solution to consider. One challenge with this solution however, is that there isn’t an easy way for higher ed technologists to get hands-on with the solution without going through a series of sales conversations.
Introducing the Snowfakery Recipe Template for Student Success Hub
The Data Generation Tookit project team is a volunteer group within the Salesforce.org Community Sprints initiative contributing open source tools and resources for organizations in the nonprofit and education sectors. Over the past two community sprints, the team has been working on a data generation solution for Student Success Hub and is now ready to share publicly.
This post provides technologists in the higher ed sector an opportunity to explore and demo a holistic student lifecycle support solution and also highlights a number of useful Snowfakery features.
What is Snowfakery?
Snowfakery is an open source tool developed by Salesforce.org that creates fake data with complex relationships and can handle large data volumes. Snowfakery is unique from other data generation tools in that it was built to address Salesforce-specific problems such as managing relationships and inserting a high volume of related records seamlessly into a Salesforce org.
Prerequisites
- Install Visual Studio Code
- Install SFDX extension for VSC
- Install Git
- Install CumulusCI
- Setup DevHub
Create Scratch Org with Student Success Hub Data Model
At the time of writing this post, a full featured trial of Student Success Hub (SSH) is not available, but it is possible to create a scratch org and install the SSH data model for the purposes of working with the sample data generation recipe.
# clone the Snowfakery recipes repository
git clone https://github.com/SFDO-Community-Sprints/Snowfakery-Recipe-Templates.git
# navigate to newly created project
cd Snowfakery-Recipe-Templates
# create scratch org with EDA and Student Success Hub data model installed
cci flow run eda:trial_org --org dev
cci flow run sal:install_base --org dev
If you already have access to a development/test environment with the Student Success Hub installed, you can use the data generation script with that environment by connecting CumulusCI to your existing environment instead of creating a scratch org.
Once the scratch org is created and the packages installed, run the data generation script and open the org
# replace 'dev' in the following commands with the CCI alias of the connected org if not using a scratch org
# generate and load fake data
cci task run snowfakery --recipe snowfakery_samples/EDA/eda_student_success_hub.yml --org dev
# open the org
cci org browser dev
Snowfakery Recipe
The Data Generation Toolkit team maintains Snowfakery recipes in a dedicated GitHub project. The recipe template for the Student Success Hub is located in the snowfakery_samples/EDA directory. The recipe is displayed below for ease of access.
# Snowfakery recipe for the Student Success Hub (formerly known as Adivsor Link) | |
# Creates data for the following objects: | |
# Contact | |
# Case (Advising Record) | |
# Case Team Role | |
# Case Team Member | |
# Case Comment | |
# Account (University Department) | |
# Advising Pool | |
# Queue Waiting Room Resource | |
# Appointment Location | |
# Availability | |
# Availability Location | |
# Availability Topic | |
# User Topic Setting | |
# Role Topic Setting | |
# Queue Topic Setting | |
# Appointment | |
# Appointment Attendee | |
# Success Plan Template | |
# Success Plan Task Template | |
# Success Plan | |
# Success Plan Task | |
# Task | |
# Alert | |
# Prediction | |
# Run this to generate data in a scratch org: | |
# cci task run snowfakery –recipe snowfakery_samples/EDA/eda_student_success_hub.yml –org dev | |
# Run this to generate records in an output JSON file (NOTE: update the org_name to the CCI org you are using) | |
# snowfakery ./snowfakery_samples/EDA/eda_student_success_hub.yml –output-format=json –output-file=snowfakery_samples/temp/output.json –plugin-option org_name dev | |
# Load plugin for querying Salesforce, used to link records to internal advisor user | |
– plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery | |
# Create Contact', 'dependency for Case (Advising) | |
– object: Contact | |
fields: | |
LastName: | |
fake: LastName | |
FirstName: | |
fake: FirstName | |
MailingStreet: | |
fake.text: | |
max_nb_chars: 100 | |
MailingCity: | |
fake: city | |
MailingState: | |
fake: state | |
MailingPostalCode: | |
fake: postalcode | |
MailingCountry: "United States" | |
Phone: | |
fake: phone_number | |
MobilePhone: | |
fake: phone_number | |
HomePhone: | |
fake: phone_number | |
hed__PreferredPhone__c: "Mobile Phone" | |
Email: | |
fake: Email | |
LeadSource: | |
random_choice: | |
– Web | |
– Phone Inquiry | |
– Partner Referral | |
– Purchased List | |
– Other | |
Birthdate: | |
date_between: | |
start_date: -50y | |
end_date: -18y | |
Description: | |
fake.text: | |
max_nb_chars: 100 | |
friends: | |
# Set primary department | |
– object: hed__Affiliation__c | |
fields: | |
hed__Account__c: | |
reference: SampleAcademicDepartment | |
hed__Contact__c: | |
reference: Contact | |
hed__Primary__c: "True" | |
hed__Description__c: | |
fake: catch_phrase | |
hed__StartDate__c: | |
date_between: | |
start_date: -1y | |
end_date: today | |
hed__EndDate__c: | |
date_between: | |
start_date: today | |
end_date: +1y | |
hed__Role__c: "Student" | |
# Create Case (Advising) record', 'dependency for Appointment, Appointment Attendee, Alert, Prediction, Success Plan, Task | |
– object: Case | |
nickname: SampleAdvisingCase | |
fields: | |
ContactId: | |
reference: Contact | |
Subject: ${{fake.Text(max_nb_chars=80)}} | |
Description: ${{fake.Paragraph(nb_sentences=3)}} | |
# sfal__IsAdviseeRecord__c: true #field is not editable by system admins | |
hed__Category__c: "Other" | |
sfal__AdvisingPool__c: | |
reference: AdvisingPool | |
sfal__Location__c: "Other" | |
hed__Location__c: "Other" | |
friends: | |
– object: CaseTeamRole | |
fields: | |
AccessLevel: Edit | |
# CaseTeamRoles must be unique so random number is added to allow recipe to run multiple times in same org | |
Name: Advisor ${{random_number(min=5, max=20)}} | |
PreferencesVisibleInCSP: true | |
friends: | |
– object: CaseTeamMember | |
fields: | |
MemberId: | |
SalesforceQuery.find_record: | |
from: User | |
where: UserType='Standard' | |
ParentId: | |
reference: SampleAdvisingCase | |
TeamRoleId: | |
reference: CaseTeamRole | |
– object: CaseComment | |
count: 3 | |
fields: | |
ParentId: | |
reference: SampleAdvisingCase | |
CommentBody: ${{fake.Text(max_nb_chars=200)}} | |
# Create University Department | |
– object: Account | |
nickname: SampleAcademicDepartment | |
fields: | |
name: Sample Academic Department | |
RecordType: "University_Department" | |
# Create Advising Pool', 'dependency for Queue Topic Setting | |
– object: sfal__AdvisingPool__c | |
nickname: AdvisingPool | |
fields: | |
sfal__Account__c: | |
reference: SampleAcademicDepartment | |
sfal__Description__c: ${{fake.Text(max_nb_chars=200)}} | |
friends: | |
# Create Queue Waiting Room Resource | |
– object: sfal__QueueWaitingRoomResource__c | |
fields: | |
sfal__AdvisingPool__c: | |
reference: AdvisingPool | |
sfal__SortOrder__c: 1 | |
sfal__User__c: | |
SalesforceQuery.find_record: | |
from: User | |
where: UserType='Standard' | |
# Objects nested with Topic | |
– object: sfal__Topic__c | |
nickname: SampleTopic | |
fields: | |
Name: | |
random_choice: | |
– Transcripts | |
– Grades | |
– Program Questions | |
sfal__SortOrder__c: 1 | |
sfal__Label__c: ${{SampleTopic.Name}} | |
friends: | |
– object: sfal__UserTopicSetting__c # create User Topic Setting associated with the Topic | |
fields: | |
sfal__DefaultAppointmentDuration__c: 30 | |
sfal__Topic__c: | |
reference: sfal__Topic__c | |
sfal__User__c: | |
SalesforceQuery.find_record: | |
from: User | |
where: UserType='Standard' | |
– object: sfal__RoleTopicSetting__c | |
fields: | |
sfal__RoleName__c: | |
random_choice: | |
– Course Advisor | |
– Program Advisor | |
– Student Services | |
sfal__Topic__c: | |
reference: sfal__Topic__c | |
– object: sfal__QueueTopicSetting__c | |
fields: | |
sfal__AdvisingPool__c: | |
reference: AdvisingPool | |
sfal__Topic__c: | |
reference: sfal__Topic__c | |
# Appointment Location object is dependency for Availability Location and Appointment | |
– object: sfal__AppointmentLocation__c | |
nickname: SampleAppointmentLocation | |
fields: | |
sfal__AdditionalDetails__c: ${{fake.Paragraph(nb_sentences=5)}} | |
sfal__Building__c: ${{fake.Text(max_nb_chars=20)}} | |
sfal__Campus__c: ${{fake.Text(max_nb_chars=20)}} | |
sfal__MeetingLink__c: ${{fake.SafeDomainName}} | |
sfal__Phone__c: ${{fake.PhoneNumber}} | |
sfal__Room__c: ${{fake.Text(max_nb_chars=12)}} | |
sfal__SortOrder__c: 1 | |
sfal__Type__c: ${{fake.Text(max_nb_chars=12)}} | |
# Objects nested with Availability | |
– object: sfal__Availability__c | |
fields: | |
name: "Available Slot" | |
sfal__AppointmentType__c: | |
random_choice: | |
– Phone | |
– In-person | |
– Video Call | |
sfal__AttendeeLimit__c: | |
random_number: | |
min: 2 | |
max: 5 | |
friends: | |
– object: sfal__AvailabilityLocation__c | |
fields: | |
sfal__Availability__c: | |
reference: sfal__Availability__c | |
sfal__Location__c: | |
reference: SampleAppointmentLocation | |
– object: sfal__AvailabilityTopic__c | |
fields: | |
sfal__Availability__c: | |
reference: sfal__Availability__c | |
sfal__Topic__c: | |
reference: SampleTopic | |
# Objects nested with Appointment | |
– object: sfal__Appointment__c | |
nickname: SampleAppointment | |
fields: | |
Name: ${{fake.Sentence(nb_words=5)}} | |
sfal__AppointmentLocation__c: | |
reference: SampleAppointmentLocation | |
sfal__AdditionalConnectionInformation__c: ${{fake.Sentence(nb_words=10)}} | |
sfal__AttendeeLimit__c: 3 | |
sfal__Description__c: ${{fake.Paragraph(nb_sentences=2)}} | |
sfal__StartDateTime__c: ${{fake.date_between(start_date='-10d',end_date='today')}}T${{fake.time}}Z | |
sfal__EndDateTime__c: ${{fake.date_between(start_date='today',end_date='+1w')}}T${{fake.time}}Z | |
sfal__IsDiscoverable__c: true | |
sfal__IsWebMeeting__c: true | |
sfal__Location__c: ${{fake.Text(max_nb_chars=100)}} | |
sfal__RelatedCase__c: | |
reference: SampleAdvisingCase | |
sfal__RelatedTopic__c: | |
reference: SampleTopic | |
sfal__Topic__c: ${{fake.Word}} | |
sfal__WebMeetingLink__c: ${{fake.Url}} | |
sfal__Type__c: "Scheduled" | |
friends: | |
– object: sfal__AppointmentAttendee__c | |
fields: | |
sfal__AdviseeRecord__c: | |
reference: SampleAdvisingCase | |
sfal__Appointment__c: | |
reference: SampleAppointment | |
sfal__Comments__c: ${{fake.Text(max_nb_chars=200)}} | |
sfal__Role__c: "Organizer" | |
sfal__Status__c: | |
random_choice: | |
– Attending | |
– Cancelled | |
– No Show | |
– Checked In | |
sfal__StatusComments__c: ${{fake.Text(max_nb_chars=50)}} | |
# Objects nested with Success Plan Template | |
– object: sfal__SuccessPlanTemplate__c | |
count: 3 | |
nickname: SuccessPlanTemplate | |
fields: | |
Name: ${{fake.RandomElement(elements=('Failed Assessment', 'Lack of Academic Activity', 'New Course Enrollment'))}} | |
sfal__Active__c: true | |
sfal__Comments__c: ${{fake.Text(max_nb_chars=200)}} | |
sfal__UsageCount__c: 1 | |
friends: | |
– object: sfal__SuccessPlanTemplateTask__c | |
nickname: TemplateTask1 | |
fields: | |
Name: Call Student | |
sfal__Active__c: true | |
sfal__Comments__c: ${{fake.Text(max_nb_chars=200)}} | |
sfal__Priority__c: ${{fake.RandomElement(elements=('High', 'Medium', 'Low'))}} | |
sfal__RelativeDueDate__c: 2 | |
sfal__SuccessPlanTemplate__c: | |
reference: SuccessPlanTemplate | |
sfal__Type__c: Call | |
– object: sfal__SuccessPlanTemplateTask__c | |
nickname: TemplateTask2 | |
fields: | |
Name: Meet with Student | |
sfal__Active__c: true | |
sfal__Comments__c: ${{fake.Text(max_nb_chars=200)}} | |
sfal__Priority__c: ${{fake.RandomElement(elements=('High', 'Medium', 'Low'))}} | |
sfal__RelativeDueDate__c: 5 | |
sfal__SuccessPlanTemplate__c: | |
reference: SuccessPlanTemplate | |
sfal__Type__c: Meeting | |
– object: sfal__SuccessPlan__c | |
fields: | |
Name: ${{SuccessPlanTemplate.Name}} | |
sfal__AdviseeRecord__c: | |
reference: SampleAdvisingCase | |
sfal__Advisee__c: | |
reference: Contact | |
sfal__AutoApply__c: true | |
sfal__Comments__c: ${{SuccessPlanTemplate.sfal__Comments__c}} | |
sfal__FromTemplate__c: | |
reference: SuccessPlanTemplate | |
sfal__IsCancelled__c: false | |
sfal__IsPublished__c: true | |
sfal__Status__c: | |
random_choice: ${{fake.RandomElement(elements=('Open', 'Completed'))}} | |
sfal__NumberOfTasks__c: 2 | |
sfal__NumberOfOpenTasks__c: 2 | |
sfal__NumberOfOverdueTasks__c: 0 | |
friends: | |
– object: Task | |
nickname: Task1 | |
fields: | |
WhatId: | |
reference: sfal__SuccessPlan__c | |
OwnerId: | |
SalesforceQuery.find_record: | |
from: User | |
where: UserType='Standard' | |
Subject: ${{TemplateTask1.Name}} | |
ActivityDate: | |
date_between: | |
start_date: today | |
end_date: +2d | |
Description: ${{TemplateTask1.sfal__Comments__c}} | |
# Uncomment the type field if using a build flow or persistent org that grants running user access to this field | |
#Type: ${{TemplateTask1.sfal__Type__c}} | |
Priority: ${{TemplateTask1.sfal__Priority__c}} | |
– object: Task | |
nickname: Task2 | |
fields: | |
WhatId: | |
reference: sfal__SuccessPlan__c | |
OwnerId: | |
SalesforceQuery.find_record: | |
from: User | |
where: UserType='Standard' | |
Subject: ${{TemplateTask2.Name}} | |
ActivityDate: | |
date_between: | |
start_date: today | |
end_date: +5d | |
Description: ${{TemplateTask2.sfal__Comments__c}} | |
# Uncomment the type field if using a build flow or persistent org that grants running user access to this field | |
#Type: ${{TemplateTask2.sfal__Type__c}} | |
Priority: ${{TemplateTask2.sfal__Priority__c}} | |
# Alert and Prediction objects | |
– object: sfal__Alert__c | |
count: 3 | |
fields: | |
sfal__AdviseeRecord__c: | |
reference: SampleAdvisingCase | |
sfal__Advisee__c: | |
reference: Contact | |
sfal__AssignUsingRules__c: true | |
sfal__Comments__c: ${{fake.Text(max_nb_chars=200)}} | |
sfal__Priority__c: ${{fake.RandomElement(elements=('Urgent', 'Normal', 'Low'))}} | |
sfal__Reason__c: ${{fake.RandomElement(elements=('Grade Concern', 'Failure Concern', 'Missing/Late Assignment', 'Attendance Concern', 'Participation Concern', 'Preparedness Concern', 'Academic Integrity', 'Recognition', 'Missing/Late Application', 'Qualification Not Met', 'General Health', 'Room Change'))}} | |
sfal__Status__c: | |
random_choice: | |
– New | |
– "Acknowledged: In Progress" | |
– "Acknowledged: Redirected" | |
friends: | |
– object: sfal__Prediction__c | |
fields: | |
sfal__Alert__c: | |
reference: sfal__Alert__c | |
sfal__Appointment__c: | |
reference: SampleAppointment | |
sfal__Case__c: | |
reference: SampleAdvisingCase | |
sfal__Model__c: ${{fake.Text(max_nb_chars=20)}} | |
sfal__Type__c: ${{fake.Text(max_nb_chars=20)}} |
Recipe Highlights
This recipe template highlights several of Snowfakery’s many useful features and capabilities:
- Data model with complex relationships: use of the “friends” and “reference” features to create records for 24 related objects in one recipe
- Reference data from connected Salesforce org: use of SalesforceQuery plugin to get Id of active user in the connected org and relate several records to this user
- Fake data: use features from fakery library to generate unique and fake data of various types, including text, paragraph, phone number, URL, names, addresses, dates
- Random values: automatically populate picklists and number fields randomly from a predefined set of values, with optional weighting on value selection
- Formulas: create task records and populate fields based on related task template records, using formulas to reference the value of generated data from task template records
Resources
- Salesforce Documentation: Student Success Hub
- Student Success Hub ERD for Higher Ed
- Student Success Hub Data Dictionary for Higher Ed
- Snowfakery Documentation