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

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

Leave a Comment

Your email address will not be published. Required fields are marked *