Inserting CPT and static content at every X post, is this possible?

Depending on what your static content and ad will be, I might be tempted to create a custom post type and add an ads post and a static content post, then use @birgire post injector class to take care of the injection of these two posts where you need them. You might need to alter the injector class a bit to suite your exact needs.

I have quickly written a more generic class (which is very very basic, you should extend this) which you can use to inject any type of string content where you need it. You can (must) improve/modify/ it as you see fit. Note that no data sanitation or validation is done, so you would want to take care of that as well according you your exact need

class MultiInjector
{
    /**
     * @var array $specialContent;
     * @access protected     
     * @since 1.0.0
     */
    protected $specialContent;

    /**
     * @var array $specialContent;
     * @access protected     
     * @since 1.0.0
     */
    protected $arrayValues;

    /**
     * @var array $pairs;
     * @access protected     
     * @since 1.0.0
     */
    protected $pairs;

    /**
     * Constructor
     *
     * @param array $specialContent; = []
     * @since 1.0.0
     */         
    public function __construct( $specialContent = [] )
    {
        $this->specialContent = $specialContent;
    }

    public function init()
    {
        add_action( 'the_post', [$this, 'thePost'] );       
    }

    /**
     * Protected method specialContentValidated()
     *
     * Make sure we have post positions, if not, set defauls. Also, reset
     * all array keys to numeric values
     *
     * @since 1.0.0
     */ 
    protected function specialContentValidated()
    {
        $arrayValues = false;

        if (    $this->specialContent 
             && is_array( $this->specialContent )
        ) {
            $arrayValues = array_values( $this->specialContent );
            // Loop over the array of special content and set defaults if no custom values exist
            foreach ( $arrayValues as $key=>$value ) {
                $defaults = [
                    'content'      => 'This is default content, make sure to set your own',
                    'postPosition' => $key
                ];
                $arrayValues[$key] = wp_parse_args( $value, $defaults );
            }
        }
        $this->arrayValues = $arrayValues;
    }

    /**
     * Protected method positions()
     *
     * Save an array of $key/postPosition pairs
     *
     * @since 1.0.0
     */ 
    protected function positions()
    {
        $this->specialContentValidated();

        $pairs = false;

        if ( $this->arrayValues ) {
            foreach ( $this->arrayValues as $key=>$value )
                $pairs[$key] = $value['postPosition'];
        }

        $this->pairs = $pairs;
    }       

    public function thePost()
    {
        // Make sure this is the main query, if not, bail
        if ( !in_the_loop() )
            return;

        $this->positions();

        // Make sure we have special content to add, if not bail
        if ( false === $this->arrayValues )
            return;

        // Set a static post counter to count the amount of posts
        static $postCount = 0;

        // Search for the post position in the $this->pairs array 
        $position = array_search( $postCount, $this->pairs );
        if ( false !== $position ) {
            // Everything checks out, display our custom content
            echo $this->arrayValues[$position]['content'];
        }

        // Update the counter 
        $postCount++;
    }
}

You can then use it as follow

add_action ( 'wp', function ()
{
    $args = [
        0 => [
                'content' => 'This is my content',
                'postPosition' => 4
            ],
        1 => [
                'content' => 'This is my other content',
                'postPosition' => 6
            ]
    ];
    $q = new MultiInjector( $args );
    $q->init();
});